免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3634 | 回复: 13
打印 上一主题 下一主题

setpgid总是出错 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-03-13 18:59 |只看该作者 |倒序浏览
我用管道实现 ls|wc 命令(随意做实验用的),第一次 fork 后 exec 了 ls,第二次 fork 后 exec 了 wc,然后用管道把 ls 和 wc 连接在了一起。
我想把 ls 自己设成了一个进程组,然后把 wc 加入 ls 的进程组,这时问题就出现了,ls 设置自己为进程组长可以,但是 wc 加入的时候出现了问题。
请各位帮忙看看是怎么回事,非常感谢。

  1. #include <stdio.h>
  2. #include <sys/wait.h>
  3. #include <unistd.h>
  4. #include <errno.h>

  5. pid_t pgid = 0;

  6. int main()
  7. {
  8.         char *prog1[] = {"ls", NULL};
  9.         char *prog2[] = {"wc", NULL};
  10.         pid_t pids[10];
  11.         int pipes[2];

  12.         if(pipe(pipes) == -1){
  13.                 printf("pipe error\n");
  14.         }
  15.         printf("comm: %s, pid: %d, pgid: %d\n", "main", getpid(), getpgid(0));
  16.         if((pids[0] = fork()) == -1){
  17.                 perror("fork error");
  18.         } else if(pids[0] == 0){
  19.                 //输出
  20.                 close(pipes[0]);
  21.                 dup2(pipes[1], STDOUT_FILENO);
  22.                 close(pipes[1]);

  23.                 setpgid(0, 0);
  24.                 pgid = getpid();
  25.                 printf("ls pgid is %d\n", getpgid(0));
  26.                 if(execvp(prog1[0], prog1) == -1){
  27.                         printf("exec prog1 failed\n");
  28.                 }
  29.         } else if(pids[0] > 0){
  30.                 pgid = pids[0];
  31.                 setpgid(pids[0], pids[0]);
  32.                 printf("comm: %s: pid: %d, pgid: %d\n",
  33.                                 "ls", pids[0], getpgid(pids[0]));
  34.                 waitpid(pids[0], NULL, 0);
  35.         }
  36.         if((pids[1] = fork()) == -1){
  37.                 perror("fork error");
  38.         } else if(pids[1] == 0){
  39.                 //输入
  40.                 close(pipes[1]);
  41.                 dup2(pipes[0], STDIN_FILENO);
  42.                 close(pipes[0]);
  43.                 if(setpgid(0, pgid) == -1){
  44.                         printf("in child, wc setpgid error\n");
  45.                         printf("errorno: %d\n", errno);
  46.                 }
  47.                 printf("wc pgid is %d\n", getpgid(0));
  48.                 if(execvp(prog2[0], prog2) == -1){
  49.                         printf("exec prog2 failed\n");
  50.                 }
  51.         } else if(pids[1] > 0){
  52.                 if(setpgid(pids[1], pgid) == -1){
  53.                         printf("in parent, wc setpgid error\n");
  54.                         printf("errorno; %d\n", errno);
  55.                 }
  56.                 printf("comm: %s: pid: %d, pgid: %d\n",
  57.                                 "wc", pids[1], getpgid(pids[1]));
  58.                 close(pipes[0]);
  59.                 close(pipes[1]);
  60.                 waitpid(pids[1], NULL, 0);
  61.         }
  62.         return 0;
  63. }
复制代码

论坛徽章:
11
技术图书徽章
日期:2014-03-01 14:44:34天蝎座
日期:2014-05-21 22:11:59金牛座
日期:2014-05-30 17:06:14
2 [报告]
发表于 2012-03-13 20:39 |只看该作者
wc进程加入的时候,ls新进程组已经退出了,肯定会出错
调整代码逻辑,设法使wc setpgid时,ls进程组依然存活

论坛徽章:
0
3 [报告]
发表于 2012-03-13 21:16 |只看该作者
在同一个进程中管道的读写端为什么都关闭?

论坛徽章:
0
4 [报告]
发表于 2012-03-13 21:43 |只看该作者
回复 3# mstxrgcu


    dup2重定向之后就关闭了。

论坛徽章:
0
5 [报告]
发表于 2012-03-13 21:51 |只看该作者
回复 2# timespace


    再请教个问题,像我这种自己创建的管道实现 ls|wc 时,是先执行ls,等ls执行完了再执行wc吗?
    调整代码逻辑的话,最后统一执行 exec 行吗?谢谢。

论坛徽章:
11
技术图书徽章
日期:2014-03-01 14:44:34天蝎座
日期:2014-05-21 22:11:59金牛座
日期:2014-05-30 17:06:14
6 [报告]
发表于 2012-03-13 22:22 |只看该作者
数据流向肯定是ls到wc,但不一定要ls完全结束才开始执行wc
管道的一个重大优点就在于很多时候可以并行执行,比如ls在写,wc读,完全不冲突

有个简单技巧,就是创建子进程的顺序与数据流相反:
1. main先创建wc进程,wc很可能在管道上读阻塞
2. main继续再创建ls进程,ls在管道上写
3. main waitpid
这样就可以利用管道的阻塞特性做到进程同步,那么setpgid就会成功了

论坛徽章:
0
7 [报告]
发表于 2012-03-13 23:09 |只看该作者
关闭之后没有影响?

论坛徽章:
0
8 [报告]
发表于 2012-03-13 23:27 |只看该作者
回复 7# mstxrgcu


    没有,已经重定向了。

论坛徽章:
0
9 [报告]
发表于 2012-03-13 23:29 |只看该作者
回复 6# timespace

我这样写就setpgid成功了。您说的意思是这样吗?还有一个问题是我这样输出的结果与直接在shell中敲 ls|wc 输出的结果不同是因为管道文件的缘故吗?谢谢。
  1. #include <stdio.h>
  2. #include <sys/wait.h>
  3. #include <unistd.h>
  4. #include <errno.h>

  5. pid_t pgid = 0;

  6. int main()
  7. {
  8.         char *prog1[] = {"ls", NULL};
  9.         char *prog2[] = {"wc", NULL};
  10.         pid_t pids[10];
  11.         int pipes[2];

  12.         if(pipe(pipes) == -1){
  13.                 printf("pipe error\n");
  14.         }
  15.         printf("comm: %s, pid: %d, pgid: %d\n", "main", getpid(), getpgid(0));

  16.         if((pids[1] = fork()) == -1){
  17.                 perror("fork error");
  18.         } else if(pids[1] == 0){
  19.                 //输入
  20.                 close(pipes[1]);
  21.                 dup2(pipes[0], STDIN_FILENO);
  22.                 close(pipes[0]);
  23.                 setpgid(0, 0);
  24.                 pgid = getpid();

  25.                 printf("wc pgid is %d\n", getpgid(0));
  26.                 if(execvp(prog2[0], prog2) == -1){
  27.                         printf("exec prog2 failed\n");
  28.                 }
  29.         } else if(pids[1] > 0){
  30.                 pgid = pids[1];
  31.                 if(setpgid(pids[1], pgid) == -1){
  32.                         printf("in parent, wc setpgid error\n");
  33.                         printf("errorno; %d\n", errno);
  34.                 }
  35.                 printf("comm: %s: pid: %d, pgid: %d\n",
  36.                                 "wc", pids[1], getpgid(pids[1]));
  37.                 //close(pipes[0]);
  38.                 //close(pipes[1]);
  39.         }
  40.         if((pids[0] = fork()) == -1){
  41.                 perror("fork error");
  42.         } else if(pids[0] == 0){
  43.                 //输出
  44.                 close(pipes[0]);
  45.                 dup2(pipes[1], STDOUT_FILENO);
  46.                 close(pipes[1]);
  47.                 if(setpgid(0, pgid) == -1){
  48.                         printf("in child, ls setpgid error\n");
  49.                         printf("errorno: %d\n", errno);
  50.                 }
  51.                 printf("ls pgid is %d\n", getpgid(0));
  52.                 if(execvp(prog1[0], prog1) == -1){
  53.                         printf("exec prog1 failed\n");
  54.                 }
  55.         } else if(pids[0] > 0){
  56.                 setpgid(pids[0], pgid);
  57.                 printf("comm: %s: pid: %d, pgid: %d\n",
  58.                                 "ls", pids[0], getpgid(pids[0]));
  59.                 waitpid(pids[0], NULL, 0);
  60.         }
  61.         close(pipes[0]);
  62.         close(pipes[1]);
  63.         waitpid(pids[1], NULL, 0);
  64.         return 0;
  65. }
复制代码

论坛徽章:
0
10 [报告]
发表于 2012-03-14 01:44 |只看该作者
回复 6# timespace


    不好意思啊,我还有一个问题,两个进程成功了,但三个时有问题了,不是setpgid的问题,应该是管道的问题。我实现 ls|more|wc ,我创建的顺序是wc,more和ls,程序没有结果而且总是不结束,请帮忙看一下原因,麻烦您了。

  1. /*
  2. * ls | more | wc,使这三个在一个进程组
  3. */
  4. #include <stdio.h>
  5. #include <unistd.h>
  6. #include <sys/wait.h>

  7. pid_t pgid;

  8. int main()
  9. {
  10.         pid_t pids[10];
  11.         int pipes[10][2];
  12.         char *ls[] = {"ls", NULL};
  13.         char *more[] = {"more", NULL};
  14.         char *wc[] = {"wc", NULL};
  15.         int i;

  16.         printf("comm: main, pid: %d, pgid: %d\n", getpid(), getpgid(0));
  17.         /*
  18.          * wc
  19.          */
  20.         for(i = 0; i < 10; i++){
  21.                 if(pipe(pipes[i]) == -1){
  22.                         printf("pipe error\n");
  23.                 }
  24.         }
  25.         if((pids[2] = fork()) == -1){
  26.                 perror("fork error");
  27.         } else if(pids[2] == 0){
  28.                 //输入
  29.                 close(pipes[1][1]);
  30.                 dup2(pipes[1][0], STDIN_FILENO);
  31.                 close(pipes[1][0]);
  32.                 if(setpgid(0, 0) == -1){
  33.                         printf("in child, %s setpgid error\n", wc[0]);
  34.                 }
  35.                 pgid = getpgid(0);
  36.                 if(execvp(wc[0], wc) == -1){
  37.                         printf("exec %s failed\n", ls[0]);
  38.                 }
  39.         } else if(pids[2] > 0){
  40.                 pgid = pids[2];
  41.                 if(setpgid(pids[2],pids[2]) == -1){
  42.                         printf("in parent, %s setpgid error\n", wc[0]);
  43.                 }
  44.                 printf("comm: %s, pid: %d, pgid: %d\n", wc[0], pids[2], getpgid(pids[2]));
  45.         }
  46.         /*
  47.          * more
  48.          */
  49.         if((pids[1] = fork()) == -1){
  50.                 perror("fork error");
  51.         } else if(pids[1] == 0){
  52.                 //输入
  53.                 close(pipes[0][1]);
  54.                 dup2(pipes[0][0], STDIN_FILENO);
  55.                 close(pipes[0][0]);
  56.                 //输出
  57.                 close(pipes[1][0]);
  58.                 dup2(pipes[1][1], STDOUT_FILENO);
  59.                 close(pipes[1][1]);
  60.                 if(setpgid(0, pgid) == -1){
  61.                         printf("in child, %s setpgid error\n", more[0]);
  62.                 }
  63.                 if(execvp(more[0], more) == -1){
  64.                         printf("exec %s failed\n", more[0]);
  65.                 }
  66.         } else if(pids[1] > 0){
  67.                 if(setpgid(pids[1], pgid) == -1){
  68.                         printf("in parent, %s setpgid error\n", more[0]);
  69.                 }
  70.                 printf("comm: %s, pid: %d, pgid: %d\n", more[0], pids[1], getpgid(pids[1]));
  71.         }
  72.         /*
  73.          * ls
  74.          */
  75.         if((pids[0] = fork()) == -1){
  76.                 perror("fork error");
  77.         } else if(pids[0] == 0){
  78.                 //输出
  79.                 close(pipes[0][0]);
  80.                 dup2(pipes[0][1], STDOUT_FILENO);
  81.                 close(pipes[0][1]);
  82.                 if(setpgid(0, pgid) == -1){
  83.                         printf("in child, %s setpgid error\n", ls[0]);
  84.                 }
  85.                 if(execvp(ls[0], ls) == -1){
  86.                         printf("exec %s failed\n", ls[0]);
  87.                 }
  88.         } else if(pids[0] > 0){
  89.                 if(setpgid(pids[0], pgid) == -1){
  90.                         printf("in parent, %s setpgid error\n", ls[0]);
  91.                 }
  92.                 printf("comm: %s: pid: %d, pgid: %d\n", ls[0], pids[0], getpgid(pids[0]));
  93.                 waitpid(pids[0], NULL, 0);
  94.         }
  95.         waitpid(pids[1], NULL, 0);
  96.         close(pipes[0][0]);
  97.         close(pipes[0][1]);
  98.         waitpid(pids[2], NULL, 0);
  99.         close(pipes[1][0]);
  100.         close(pipes[1][1]);
  101.         return 0;
  102. }
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP