进程间通信之管道通信(一)

来源:互联网 发布:青岛淘宝运营培训机构 编辑:程序博客网 时间:2024/06/15 21:46
管道Pipe
pipe是系统调用;
pipe只能进行进程间的单向通信;
(1)创建管道
         匿名管道的创建:int pipe(fd[2]);
         当一个进程调用pipe成功后,则这个进程以读方式和写方式分别打开一个pipe文件,那么:fd[0]保存读方式打开的文件描述符,fd[1]保存以写              
         方式打开的文件描述符; 
         命名管道的创建:int mkfifo(const char* pathname,mode_t mode);
(2)创建进程:
         匿名管道:匿名管道只能用于具有血缘的进程间通信;通常用于父子进程间的通信;int fork();
         注:父子进程可以使用匿名管道进行进程间通信,是由于父子进程具有相同的文件描述符表;
         命名管道:用于任何两个进程间的通信;
管道的特点:
(1)单向通信;
(2)管道的生命周期随进程;
(3)管道对于上层提供面向字节流的通信服务;
(4)管道通信自带同步机制。(防止写入时覆盖数据,读数据时读出垃圾数据)
(5)匿名管道:只能用于具有血缘关系的进程间的通信,常用于父子进程间的通信;
        命名管道:用于任意进程间的通信;
管道通信的四种情况:
(1)当父进程不读时,也不关闭读fd时:子进程把pipe写满就停下来等待父进程读数据(以阻塞方式等待);
(2)当子进程不写时,也不关闭写fd时:父进程读完pipe中的数据,就停下来等待子进程写数据(以阻塞方式            等待);
 注:(1)(2)证明管道通信自带同步机制;
(3)父进程不读并且关闭读fd:系统会终止子进程;
4)子进程不写并且关闭写fd:父进程读pipe中的数据,读到返回0值,表示pipe中的数据读完。
注:(一)使用匿名管道进行父子进程间通信的代码:
#include<stdio.h>#include<unistd.h>int main(){//---------------creat pipe start-------------------int pipefd[2]={0};int ret = pipe(pipefd);//success return 0; failed is -1;if(ret == -1 ){perror("pipe failed");return 1;}   //---------------creat pipe end ----------------------   pid_t id = fork();   if(id ==0)   {   //child---------write   close(pipefd[0]);   char* msg = "star";   while(1)   {     write(pipefd[1],msg,sizeof(msg)-1);     sleep(1);   }   }   else   {   //father-------read   close(pipefd[1]);   char buf[1024];   while(1)   {      ssize_t s = read(pipefd[0],buf,sizeof(buf)-1);      if(s>0) //read success      {     buf[s] = 0;     printf("father is read:%s\n",buf);      }  }   }return 0;}
(二)使用命名管道进行任意两个进程间通信
  (1)client端的代码:
//client -------------write data from named pipe#include<stdio.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<unistd.h>#include<string.h>int main(){    int fd = open("./mypipe",O_WRONLY);if(fd < 0) //open file failed{perror("open file.");return 2;}if(fd >0) //open file success{char buf[1024];while(1){  printf("Please Enter:");  ssize_t s = read(0,buf,sizeof(buf)-1);  if(s>0)   //read success  {  buf[s] = 0;  write(fd,buf,strlen(buf));  }  else  {  //read failed  perror("read data.");  return 3;  }}}    close(fd);return 0;}
(2)server端的代码:
//server -------------read data from named pipe#include<stdio.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<unistd.h>int main(){umask(0);//creat a pipe of named mypipeint ret = mkfifo("./mypipe",S_IFIFO|0666);//success return 0;failed return -1;if(ret < 0){//creat pipe failedperror("creat pipe.");return 1;}if(ret == 0){//creat pipe success    int fd = open("./mypipe",O_RDONLY);if(fd < 0) //open file failed{perror("open file.");return 2;}if(fd >0) //open file success{char buf[1024];while(1){  ssize_t s = read(fd,buf,sizeof(buf)-1);  if(s>0)   //read success  {  buf[s-1] = 0;  printf("client# %s\n",buf);  }  else  {  if(s<0)  {    //read failed    perror("read file.");    return 3;  }  if(s == 0)  {  printf("client is quit.\n");  break;  }  }}}}return 0;}
(3)Makefile的实现:
.PHONY:allall:client serverserver:server.cgcc -o $@ $^client:client.cgcc -o $@ $^.PHONY:cleanclean:rm -rf server client mypipe


作者水平有限,如有问题,请留言,谢谢!!!



原创粉丝点击