Chinaunix首页 | 论坛 | 博客
  • 博客访问: 208625
  • 博文数量: 64
  • 博客积分: 2010
  • 博客等级: 上尉
  • 技术积分: 720
  • 用 户 组: 普通用户
  • 注册时间: 2008-02-25 19:03
文章分类

全部博文(64)

文章存档

2013年(1)

2012年(9)

2011年(25)

2010年(7)

2009年(16)

2008年(6)

分类: LINUX

2011-09-07 09:20:13

    本文以一个例子来演示通过管道如何实现进程间通讯。(一个进程是自己的进程,另一个进程是自己进程创建的shell进程。)以及在实现中得到的体会。
    1.管道的创建
      管道的创建函数如下:
 
      #include
      int pipe(int pipefd[2]);
 
      #define _GNU_SOURCE    
      #include
      int pipe2(int pipefd[2], int flags);

     (1).pipefd[0]:为读打开,pipefd[1]:为写打开。 pipefd[1]的输出是pipefd[0]的输入。    

      (2).创建失败时返回-1,成功返回0.

      (3).pipe2中,当flags=0,相当于pipe。flags 有 O_NONBLOCK ,设置两个管道为非阻塞模式,flags有 O_CLOEXEC   时,设置。。。。。

   2.管道的一般应用都是和fork结合起来使用。这样两个进程就能通讯。

   3.fork函数:

   #include <>

   #include <>

   pid_t fork(void);

  fork函数返回值若是大于0,则表示本进程是父进程,若返回值等于0,则表示本进程是子进程。若小于0,则表示出错。

   4.例子:

  1. #include <signal.h>
  2. #include <fcntl.h>
  3. #include <sys/types.h>
  4. #include <dirent.h>
  5. #include <sys/stat.h>
  6. #include <unistd.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <sys/wait.h>

  11. #include <sys/syscall.h>
  12. #include <setjmp.h>

  13. #define BUFFER_SIZE 4096

  14. #define DEBUG

  15. int fd1[2] = {-1,-1},fd2[2] ={-1,-1};
  16. bool bStartShell = false;

  17. void AppendLog(char *log)
  18. {
  19. }


  20. static void sig_pipe(int sig)
  21. {
  22.     return ;
  23. }

  24. pid_t pid;

  25. char lineEOF[3]={0xd,0xa,0};

  26. bool RunCmd(char* recvBuf,int recvlen,char* sendBuf);

  27. bool StartShell(char* line)
  28. {    
  29.     if(bStartShell)    return 1;
  30.     signal(SIGPIPE,SIG_IGN);
  31.     //创建两个管道,一个管道是为了向写,另一个是为了读取结果。
  32.     
  33.     if(pipe(fd1) < 0 || pipe(fd2) < 0)
  34.         return 0;

  35.     //以上内容父、子进程共享

  36.     signal(SIGCHLD,SIG_IGN);

  37.     if((pid=fork()) < 0) //创建子进程错误。
  38.     {
  39.         close(fd2[0]);close(fd2[1]);
  40.         return 0;
  41.     }
  42.     
  43.     else if(pid) //parent process
  44.     {
  45.         //AppendLog("parent process");
  46.         signal(SIGHUP,SIG_IGN);
  47.         
  48.         //父进程向fd1[1]写,从fd2[0]读最后的结果。
  49.         
  50.         close(fd1[0]);     close(fd2[1]);

  51.         char cmd[100];

  52.         bool bok;

  53.         while(1)
  54.         {
  55.             if(fgets(cmd,100,stdin)==NULL) break;
  56.             printf("cmd = %s\n",cmd);

  57.             bok = RunCmd(cmd,strlen(cmd),line);
  58.             printf("output = %s\n",line);
  59.         }

  60.         return 0;
  61.     }
  62.     else//child process
  63.     {
  64.         char Msg[100];

  65.         //子进程,输入为fd1[0],输出为fd2[1],
  66.         
  67.         close(fd1[1]);    close(fd2[0]);         
  68.         
  69.        //定义shell的标准输入为fd1[0]

  70.         if(fd1[0] != STDIN_FILENO)
  71.         {
  72.             if(dup2(fd1[0],STDIN_FILENO) != STDIN_FILENO) {
  73.                  AppendLog("dup2 fd1[0] error");
  74.                  close(fd1[0]);
  75.             }
  76.         }
  77.         //定义shell的标准输出为fd2[1]
  78.          if(fd2[1] != STDOUT_FILENO)
  79.         {
  80.               if(dup2(fd2[1],STDOUT_FILENO) != STDOUT_FILENO) {
  81.                   AppendLog("dup2 fd2[1] error");
  82.                   close(fd2[1]);
  83.               }
  84.         }
  85.         //把stdin,stdout设置为行缓冲,每次读/写一行。

  86.         setvbuf(stdin,NULL,_IOLBF,0);
  87.         setvbuf(stdout,NULL,_IOLBF,0);
  88.       
  89.         //子进程为shell。

  90.         if(execl("/bin/sh","sh",(char*)0) < 0) return 0;
  91.     }
  92.     return 1;
  93. }


  94. static jmp_buf env_alrm;

  95. static void sig_alrm(int signo)
  96. {    
  97.     //AppendLog("sig_alarm");
  98.     longjmp(env_alrm,1);
  99.     exit(1);
  100. }

  101. bool RunCmd(char* recvBuf,int recvLen,char* sendBuf)
  102. {
  103.     if(recvBuf == 0) return 0;
  104.     if(recvLen == 0) return 0;
  105.     if(sendBuf == 0) return 0;
  106.     if((fd1[1]==-1 || fd2[0]==-1) &&!bStartShell) return 1;
  107.         
  108.     int n;
  109.     char line[BUFFER_SIZE];
  110.     
  111.     strcpy(line,(const char *)recvBuf);
  112.     line[recvLen] = 0xa;
  113.     printf("recv = %s\n",line);

  114.     if((line[1]=='e' || line[1]=='E') &&
  115.      (line[2]=='x' || line[2]=='X') &&
  116.      (line[3]=='i' || line[3]=='I') &&
  117.      (line[4]=='t' || line[1]=='T'))
  118.     {
  119.         if(write(fd1[1],line,recvLen+1)!=recvLen) return 0;
  120.         close(fd1[1]);
  121.         close(fd2[0]);
  122.         fd1[1] = -1;
  123.         fd2[0] = -1;
  124.         bStartShell = false;
  125.     }

  126.     pid = fork();
  127.     
  128.     if(pid) //farther process ,负责向shell进程发送命令
  129.     {
  130.         signal(SIGHUP,SIG_IGN);
  131.         
  132.         AppendLog(line);
  133.         
  134.         int ret = write(fd1[1],line,recvLen);
  135.     
  136.         if(ret <0)
  137.         {
  138.             //AppendLog("write fd1[1] fail");
  139.             close(fd1[1]);close(fd2[0]);
  140.             bStartShell = false;
  141.             write(fd1[1],line,recvLen+1);
  142.         }

  143.         AppendLog("write fd1[1] ok");

  144.         if((line[1] =='c'||line[1]=='C') && line[2]=='d'||line[2]=='D')
  145.         {
  146.             strcpy(line,"pwd");
  147.             line[3]=0xa;
  148.             write(fd1[1],line,4);
  149.         }

  150.         AppendLog("wait read ......");
  151.        //等待子进程结束,意味着读取命令结果成功。
  152.         waitpid(pid,NULL,0);
  153.         //sleep(10);
  154.         //n = read(fd2[0],line,BUFFER_SIZE);
  155.         //if(n < 0) {printf("read error");exit(0);}
  156.         //else if(n==0) { AppendLog("pipe closed");exit(0);}
  157.         //else
  158.         //    printf("%s\n",line);

  159.         //AppendLog("waitpid over!");
  160.             
  161.     }
  162.     else //子进程,负责执行结果的读取。
  163.     {
  164.         memset(sendBuf,0,BUFFER_SIZE);
  165.         int flag = false;
  166.         signal(SIGALRM,sig_alrm);
  167.         setjmp(env_alrm);
  168.         char Msg[200];
  169.         do
  170.         {
  171.             alarm(5);
  172.             AppendLog("......read.....");
  173.             n = read(fd2[0],line,BUFFER_SIZE-1);
  174.             if(n < 0) break;
  175.             alarm(0);            

  176.             sprintf(Msg,"read n = %d",n);
  177.             printf("%s\n",line);
  178.         }while(n == BUFFER_SIZE-1);
  179.         exit(0);
  180.     }
  181.     return 1;
  182. }


  183. int main()
  184. {
  185.     bool bok ;
  186.     char cmd[BUFFER_SIZE],line[BUFFER_SIZE];

  187.     bok = StartShell(line);
  188. }

 

 

 



 
阅读(695) | 评论(0) | 转发(0) |
0

上一篇:完成端口socket

下一篇:冰与火之歌 卷一

给主人留下些什么吧!~~