管道到C中的grep程序

管道到C中的grep程序,c,linux,fork,pipeline,C,Linux,Fork,Pipeline,我正在尝试将这个bash命令:ps aux | grep bash复制到C语言。我写了一些东西,但似乎不起作用。结果实际上是什么也没有发生,提示在bash中再次打印。代码如下: int main() { int pid; int pip[2]; char *argexec1[] = {"/bin/grep", "bash", NULL}; char *argexec2[] = {"/bin/ps", "aux",

我正在尝试将这个bash命令:
ps aux | grep bash
复制到C语言。我写了一些东西,但似乎不起作用。结果实际上是什么也没有发生,提示在bash中再次打印。代码如下:

int main()
{

int pid;
int pip[2];
char *argexec1[] = {"/bin/grep", "bash", NULL};
char *argexec2[] = {"/bin/ps", "aux", NULL};

if (pipe(pip) == -1){
        perror("pipe error \n");
        exit(1);
}

if (pid = fork() == -1){
        perror("fork error");
        exit(1);
}

if (pid == 0)
{
        dup2(pip[0], 0);
        close(pip[1]);
        close(pip[0]);

        execvp("grep", argexec1);
        perror("exec1 failed\n");
        exit(1);

}

else
{
    dup2(pip[1], 1);
    close(pip[0]);
    close(pip[1]);

    execvp("ps", argexec2);
    perror("exec2 failed\n");
    exit(1);
}
在子进程中,如果execvp()失败,则不要调用exit(),而是调用_exit(),否则继承的I/O上下文可能会触发重复的I/O刷新和其他一些不需要的事情

。“==”的值大于“=”。这使得您的声明在此处失败:

if (pid = fork() == -1)
添加括号:

if ((pid = fork()) == -1)
以下是您的程序和修复程序:

#包括
#包括
#包括
内部主(空)
{
int-pid;
int-pip[2];
char*argexec1[]={“/bin/grep”,“bash”,NULL};
char*argexec2[]={/bin/ps”,“aux”,NULL};
如果(管道(pip)=-1){
perror(“管道错误”);
出口(1);
}
如果((pid=fork())=-1){
perror(“分叉错误”);
出口(1);
}
如果(pid==0){
//子进程
dup2(pip[0],0);
关闭(pip[1]);
关闭(pip[0]);
执行副总裁(“grep”,argexec1);
perror(“exec1失败\n”);
_出口(1);
}否则{
//父进程
dup2(pip[1],1);
关闭(pip[0]);
关闭(pip[1]);
执行副总裁(“ps”,argexec2);
perror(“exec2失败\n”);
出口(1);
}
返回0;
}
但实际上,如果您想让它像shell一样,那么应该在退出程序之前等待命令结束,并返回管道中最后一个进程的退出代码。因此,父亲应该启动两个过程并等待它们的结束:

#包括
#包括
#包括
#包括
内部主(空)
{
int状态1、状态2;
int-pid1,pid2;
int-pip[2];
char*argexec1[]={“/bin/grep”,“bash”,NULL};
char*argexec2[]={/bin/ps”,“aux”,NULL};
如果(管道(pip)=-1){
perror(“管道错误”);
出口(1);
}
if((pid1=fork())=-1){
perror(“分叉错误”);
出口(1);
}
如果(pid1==0){
//子进程#1
dup2(pip[0],0);
关闭(pip[1]);
关闭(pip[0]);
执行副总裁(“grep”,argexec1);
perror(“exec1失败\n”);
_出口(2);
}否则{
//父进程
if((pid2=fork())=-1){
perror(“分叉错误”);
出口(1);
}
如果(pid2==0){
//子进程#2
dup2(pip[1],1);
关闭(pip[1]);
关闭(pip[0]);
执行副总裁(“ps”,argexec2);
perror(“exec2失败\n”);
_出口(2);
}否则{
//父进程
关闭(pip[0]);
关闭(pip[1]);
//等待节目结束
如果(-1==waitpid(pid1和状态1,0)){
perror(“wait1错误”);
出口(1);
}
如果(-1==waitpid(pid2和状态2,0)){
perror(“wait2错误”);
出口(1);
}
//返回管道中最后一个程序的退出代码
如果(妻子退出(状态1)){
返回WEXITSTATUS(状态1);
}否则{
//进程可能已经收到一个信号,返回整个状态。。。
返回状态1;
}
}
}
返回0;
}

请贴上与专业知识将帮助人们回答问题的项目相关的标签。作为一名bash专家并不能让这个问题更容易回答;作为一名grep专家也是如此。特别需要的是C方面的专业知识。阅读、使用或的源代码,并从中获得灵感。使用所有警告和调试信息编译:
gcc-Wall-Wextra-g
如果您不需要来自
ps aux
的很多信息,那么只需避免使用
ps aux | grep bash
并使用
pgrep-l bash
即可,这会更快(因为只生成一个进程)且更正确(因为在调用
grep
之前,进程列表可能已经更改。谢谢。还有一件事,当我执行程序时,它工作正常,只是最后它给了我一个错误:“信号17(CHLD)被ps(未知)/bin/ps:ps/display捕获。c:66:请报告此错误”是的,这是预期的,因为父进程分叉一个子进程并执行“ps”。但是一个进程应该在退出之前等待其子进程的结束。“ps”程序不知道它有子进程要等待。通常应该分叉()2个子进程:一个代表“ps”,另一个代表“grep”。父进程将在退出之前等待终止。因此,唯一的解决方法是两次分叉?否则无法解决?此外,主程序应返回管道中最后一个进程的退出代码。在这里,您应返回grep的退出代码。您必须两次分叉()。