使用 Pipes 和 exec() 来控制另一个控制台应用程序
Using Pipes and exec() to control another console application
我正在尝试自学一些重定向。我有以下问题:
我有一个简单的程序,它要求用户输入一个整数,然后输出一些其他整数,它会无限期地执行,直到用户输入 0,然后关闭。
我正在尝试为该程序编写一个包装器,将来它可能是另一个控制台应用程序的一些 GUI 包装器。
目标是与该程序通信。
我的第一个想法是使用管道,fork 进程,将管道设置为子进程的 stdin 和 stdout,然后 exec() 控制台应用程序。
现在,到目前为止,我的代码无法正常工作,因为控制台应用程序确实得到了执行,但它照常运行,在控制台中,输出没有到达我想要的位置。
main()
{
int master_to_slave[2];
int slave_to_master[2];
pipe(master_to_slave);
pipe(slave_to_master);
int pid;
if((pid=fork())==0){
close(master_to_slave[1]);
close(slave_to_master[0]);
dup2(0, master_to_slave[0]);
dup2(1, slave_to_master[1]);
char *args[] = { NULL };
execv("/home/ebach/Documents/HIWI/random.exe",args);
}
else if(pid<0){
//ALARM ALARM
}
else{
close(master_to_slave[0]);
close(slave_to_master[1]);
while(1){
char buff[16];
int rd = read(slave_to_master[0], &buff, sizeof(buff));
if(rd > 0){
buff[rd-1] = '[=10=]';
printf("Redirected: ");
for(int i = 0; i < rd; i++){
printf("T%c", buff[i]);
}
printf("\n");
}
}
wait(NULL);
}
}
到目前为止,它只是应该重定向控制台应用程序的输出。 (如您所见,它应该只添加 'Redirected:'
反正我对c不是很精通,所以我也找不出错。
我是不是'connect'管道错了?
我遇到的另一个解决方案是使用 forkpty() 和 exec() 来使用伪终端,我应该走那条路吗?
提前感谢您的帮助!
您使用了 dup2
倒退。根据 man page:int dup2(int fildes, int fildes2);
dup2
将导致 filedes2
引用与 filedes
.
相同的打开文件
@hacatu 似乎已经在他的回答中指出了您的主要问题。此外,
- 正如我对 hacatu 的回答所评论的那样,一旦 child
dup2()
将管端连接到标准流之一,它应该关闭该管端。例如,
dup2(slave_to_master[1], 1);
close(slave_to_master[1]);
- 提供给
execv()
或execvp()
的参数向量,以及提供给execl()
、execlp()
或execle()
的参数列表直接映射到目标程序的 argv
向量。因此,通常至少有一个元素,命名正在执行的程序。一些程序依赖于它。例如:
char *args[] = { "random.exe", NULL };
execv("/home/ebach/Documents/HIWI/random.exe", args);
不过,您可能会发现 execl()
在这种情况下更方便一些:
execl("/home/ebach/Documents/HIWI/random.exe", "random.exe", NULL);
我正在尝试自学一些重定向。我有以下问题:
我有一个简单的程序,它要求用户输入一个整数,然后输出一些其他整数,它会无限期地执行,直到用户输入 0,然后关闭。
我正在尝试为该程序编写一个包装器,将来它可能是另一个控制台应用程序的一些 GUI 包装器。 目标是与该程序通信。
我的第一个想法是使用管道,fork 进程,将管道设置为子进程的 stdin 和 stdout,然后 exec() 控制台应用程序。
现在,到目前为止,我的代码无法正常工作,因为控制台应用程序确实得到了执行,但它照常运行,在控制台中,输出没有到达我想要的位置。
main()
{
int master_to_slave[2];
int slave_to_master[2];
pipe(master_to_slave);
pipe(slave_to_master);
int pid;
if((pid=fork())==0){
close(master_to_slave[1]);
close(slave_to_master[0]);
dup2(0, master_to_slave[0]);
dup2(1, slave_to_master[1]);
char *args[] = { NULL };
execv("/home/ebach/Documents/HIWI/random.exe",args);
}
else if(pid<0){
//ALARM ALARM
}
else{
close(master_to_slave[0]);
close(slave_to_master[1]);
while(1){
char buff[16];
int rd = read(slave_to_master[0], &buff, sizeof(buff));
if(rd > 0){
buff[rd-1] = '[=10=]';
printf("Redirected: ");
for(int i = 0; i < rd; i++){
printf("T%c", buff[i]);
}
printf("\n");
}
}
wait(NULL);
}
}
到目前为止,它只是应该重定向控制台应用程序的输出。 (如您所见,它应该只添加 'Redirected:'
反正我对c不是很精通,所以我也找不出错。
我是不是'connect'管道错了?
我遇到的另一个解决方案是使用 forkpty() 和 exec() 来使用伪终端,我应该走那条路吗?
提前感谢您的帮助!
您使用了 dup2
倒退。根据 man page:int dup2(int fildes, int fildes2);
dup2
将导致 filedes2
引用与 filedes
.
@hacatu 似乎已经在他的回答中指出了您的主要问题。此外,
- 正如我对 hacatu 的回答所评论的那样,一旦 child
dup2()
将管端连接到标准流之一,它应该关闭该管端。例如,
dup2(slave_to_master[1], 1);
close(slave_to_master[1]);
- 提供给
execv()
或execvp()
的参数向量,以及提供给execl()
、execlp()
或execle()
的参数列表直接映射到目标程序的argv
向量。因此,通常至少有一个元素,命名正在执行的程序。一些程序依赖于它。例如:
char *args[] = { "random.exe", NULL };
execv("/home/ebach/Documents/HIWI/random.exe", args);
不过,您可能会发现 execl()
在这种情况下更方便一些:
execl("/home/ebach/Documents/HIWI/random.exe", "random.exe", NULL);