免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12
最近访问板块 发新帖
楼主: buzzerrookie
打印 上一主题 下一主题

setpgid总是出错 [复制链接]

论坛徽章:
11
技术图书徽章
日期:2014-03-01 14:44:34天蝎座
日期:2014-05-21 22:11:59金牛座
日期:2014-05-30 17:06:14
11 [报告]
发表于 2012-03-14 19:20 |只看该作者
回复 10# buzzerrookie
解决办法
在wc进程开始处加入:

  1. close(pipes[0][0]);
  2. close(pipes[0][1]);
复制代码
main最后一部分改为

  1.         close(pipes[0][0]);
  2.         close(pipes[0][1]);
  3.         waitpid(pids[1], NULL, 0);
  4.         close(pipes[1][0]);
  5.         close(pipes[1][1]);
  6.         waitpid(pids[2], NULL, 0);
复制代码
但还有潜在问题:
1. pipe在进程间的引用关系太乱了。比如wc完全没必要继承pipe[0][...],还有副作用。wc引用了pipes[0][1],却没关闭,导致more进程永远阻塞在read(0, ...),这是你进程退不出的原因。理顺代码,只在必要的时候创建管道,在不用的时候立即关闭
2. 用setpgid有问题。more和/dev/tty有交互,但setpgid使main子进程全部进入单独的后台进程组,不能访问/dev/tty,否则触发SIGTTIN,挂起进程。more这种终端交互命令很少会卡在管道中间,一般在最后执行,还要确保more所在进程组为前台进程组。setpgid在支持&(进入shell后台)功能时才有用,你现在用不到

强烈建议看过APUE相应章节后,模仿shell管道的进程关系,同时理解pipe用法,否则会浪费不少时间。


   

论坛徽章:
0
12 [报告]
发表于 2012-03-14 22:51 |只看该作者
回复 11# timespace


    非常感谢,还是得好好看APUE。写这个的目的是操作系统课实验让自己写个类似的简单 shell,其中有一步我用到了这些东西。再次谢谢您。

论坛徽章:
0
13 [报告]
发表于 2012-03-15 15:39 |只看该作者
本帖最后由 chllcy88 于 2012-03-15 15:40 编辑

大哥 我这个代码加了下面这个 还是阻塞在more处 不知道什么原因 忘指点下

在wc进程开始处加入:
close(pipes[0][0]);

close(pipes[0][1]);
  1. #include <stdio.h>

  2. #include <unistd.h>

  3. #include <sys/wait.h>
  4. #include <sys/types.h>
  5. #include <cstdlib>
  6. #include <iostream>
  7. using namespace std;

  8. int isready(int fd)
  9. {
  10.         int rc;
  11.         fd_set fds;
  12.         struct timeval tv;

  13.         FD_ZERO(&fds);
  14.         FD_SET(fd, &fds);
  15.         tv.tv_sec = 1;
  16.         tv.tv_usec = 0;
  17.         rc = select(fd + 1, &fds, NULL, NULL, &tv);
  18.         if (rc < 0) //error
  19.                 return -1;

  20.         return FD_ISSET(fd, &fds) ? 1 : 0;
  21. }
  22. int main()

  23. {

  24.         pid_t pids[10];

  25.         int pipes[10][2];

  26.         char *ls[] =
  27.         { "ls", NULL };

  28.         char *more[] =
  29.         { "more", NULL };

  30.         char *wc[] =
  31.         { "wc", NULL };

  32.         int i, status;

  33.         for (i = 0; i < 10; i++)
  34.         {

  35.                 if (pipe(pipes[i]) == -1)
  36.                 {

  37.                         printf("pipe error\n");

  38.                 }

  39.         }

  40.         if ((pids[0] = fork()) == -1)
  41.         {

  42.                 perror("fork error");

  43.         }
  44.         else if (pids[0] == 0)
  45.         {

  46.                 //输出

  47.                 close(pipes[0][0]);
  48.                 close(STDOUT_FILENO);

  49.                 dup2(pipes[0][1], STDOUT_FILENO);

  50.                 close(pipes[0][1]);

  51.                 if (execvp(ls[0], ls) == -1)
  52.                 {

  53.                         printf("exec %s failed\n", ls[0]);

  54.                 }

  55.         }
  56.         else if (pids[0] > 0)
  57.         {

  58.                 wait(NULL);

  59.                 if ((pids[2] = fork()) == -1)
  60.                 {

  61.                         perror("fork error");

  62.                 }
  63.                 else if (pids[2] == 0)
  64.                 {
  65.                      close(pipes[0][0]);

  66.                       close(pipes[0][1]);

  67.                         //输入
  68.                         //sleep(2);
  69.                         if (isready(pipes[0][0]) > 0)
  70.                         {
  71.                                 cout << "ready" << endl;
  72.                                 close(pipes[0][1]);
  73.                                 close(STDIN_FILENO);
  74.                                 dup2(pipes[0][0], STDIN_FILENO);

  75.                                 close(pipes[0][0]);

  76.                                 //输出

  77.                                 close(pipes[1][0]);
  78.                                 close(STDOUT_FILENO);
  79.                                 dup2(pipes[1][1], STDOUT_FILENO);
  80.                                 dup2(pipes[1][1], STDERR_FILENO);

  81.                                 close(pipes[1][1]);

  82.                                 if (execvp(more[0], more) == -1)
  83.                                 {

  84.                                         printf("exec %s failed\n", more[0]);

  85.                                 }
  86.                         }

  87.                 }
  88.                 else if (pids[2] > 0)
  89.                 {
  90.                         //输入
  91.                         wait(NULL);
  92.                         ////waitpid( pids[2], &status, 0 );

  93.                         if (isready(pipes[1][0]) > 0)
  94.                         {
  95.                                 cout << "ready 2" << endl;
  96.                                 close(pipes[1][1]);
  97.                                 close(STDIN_FILENO);

  98.                                 dup2(pipes[1][0], STDIN_FILENO);

  99.                                 close(pipes[1][0]);

  100.                                 if (execvp(wc[0], wc) == -1)
  101.                                 {

  102.                                         printf("exec %s failed\n", ls[0]);

  103.                                 }
  104.                         }

  105.                 }

  106.         }

  107.         close(pipes[0][0]);

  108.         close(pipes[0][1]);

  109.         close(pipes[1][0]);

  110.         close(pipes[1][1]);

  111.         return 0;

  112. }
复制代码

论坛徽章:
0
14 [报告]
发表于 2012-03-16 00:08 |只看该作者
回复 13# chllcy88


    我是用C给改的,就把cout换成了printf。

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <sys/wait.h>
  4. #include <sys/types.h>
  5. #include <stdlib.h>

  6. int isready(int fd)
  7. {
  8.         int rc;
  9.         fd_set fds;
  10.         struct timeval tv;

  11.         FD_ZERO(&fds);
  12.         FD_SET(fd, &fds);
  13.         tv.tv_sec = 1;
  14.         tv.tv_usec = 0;
  15.         rc = select(fd + 1, &fds, NULL, NULL, &tv);
  16.         if (rc < 0) //error
  17.                 return -1;

  18.         return FD_ISSET(fd, &fds) ? 1 : 0;
  19. }
  20. int main()
  21. {

  22.         pid_t pids[10];
  23.         int pipes[10][2];
  24.         char *ls[] = { "ls", NULL };
  25.         char *more[] = { "more", NULL };
  26.         char *wc[] = { "wc", NULL };
  27.         int i, status;

  28.         for (i = 0; i < 10; i++){
  29.                 if (pipe(pipes[i]) == -1){
  30.                         printf("pipe error\n");
  31.                 }
  32.         }

  33.         if((pids[0] = fork()) == -1){
  34.                 perror("fork error");
  35.         } else if (pids[0] == 0){
  36.                 //输出
  37.                 close(pipes[0][0]);
  38.                 close(STDOUT_FILENO);
  39.                 dup2(pipes[0][1], STDOUT_FILENO);
  40.                 close(pipes[0][1]);

  41.                 if (execvp(ls[0], ls) == -1){
  42.                         printf("exec %s failed\n", ls[0]);
  43.                 }
  44.         } else if (pids[0] > 0){
  45.                 wait(NULL);
  46.                 if ((pids[2] = fork()) == -1){
  47.                         perror("fork error");
  48.                 } else if (pids[2] == 0){
  49.                      //close(pipes[0][0]);
  50.                      //close(pipes[0][1]);
  51.                                   //输入
  52.                      //sleep(2);
  53.                      if(isready(pipes[0][0]) > 0){
  54.                              printf("ready\n");
  55.                              close(pipes[0][1]);
  56.                              close(STDIN_FILENO);
  57.                              dup2(pipes[0][0], STDIN_FILENO);
  58.                              close(pipes[0][0]);
  59.                                          //输出
  60.                              close(pipes[1][0]);
  61.                              close(STDOUT_FILENO);
  62.                              dup2(pipes[1][1], STDOUT_FILENO);
  63.                              dup2(pipes[1][1], STDERR_FILENO);
  64.                              close(pipes[1][1]);
  65.                              if (execvp(more[0], more) == -1){
  66.                                      printf("exec %s failed\n", more[0]);
  67.                                           }
  68.                                   }
  69.                 } else if (pids[2] > 0){
  70.                         close(pipes[0][0]);
  71.                         close(pipes[0][1]);
  72.                         //输入
  73.                         wait(NULL);
  74.                         //waitpid( pids[2], &status, 0 );
  75.                         if (isready(pipes[1][0]) > 0){
  76.                                 printf("ready 2\n");
  77.                                 close(pipes[1][1]);
  78.                                 close(STDIN_FILENO);
  79.                                 dup2(pipes[1][0], STDIN_FILENO);
  80.                                 close(pipes[1][0]);

  81.                                 if (execvp(wc[0], wc) == -1){
  82.                                         printf("exec %s failed\n", wc[0]);
  83.                                 }
  84.                         }

  85.                 }
  86.         }
  87.         close(pipes[0][0]);
  88.         close(pipes[0][1]);
  89.         close(pipes[1][0]);
  90.         close(pipes[1][1]);
  91.         return 0;
  92. }
复制代码
因为原来的 else if (pids[2] == 0) 这句之后 close(pipes[0][0]); close(pipes[0][1]); 管道还没用就给关闭了,所以 ls 和 more 没用管道连上。还有一个地方是 else if (pids[2] > 0) 之后 close(pipes[0][0]); close(pipes[0][1]); 把管道pipe[0]都关闭,让more结束。其实还是用时再创建管道比较好,而不是开始创建一堆,就像 timespace 说的那样。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP