进程间通信(ipc)
应用场景: 数据传输 资源共享 通知事件 进程控制 system v at&t system v posix(portable operating system interface)可移植操作系统接口 常用的进程间通信的方式: 管道(pipe)和有名管道(fifo) 信号(signal) 消息队列 共享内存 信号量 套接字(socket) 管道通信 半双工的,数据只能向一个方向流动 只能用于父子进程间或兄弟进程间 先进先出,一个进程在管道的尾部写入数据,另一个进程从管道的头部读出数据 无名管道 用于父子进程间的通信 创建管道 int pipe(int filedis[2]) 管道建立时,所创建的两个文件描述符 filedis[0] 管道的读取端 filedis[1] 管道的写入端 关闭管道 将两个文件描述符关闭 示例代码如下: #include <unistd.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> int main(){ int pipe_fd[2]; if(pipe_fd<0){ printf("pipe create error\n"); return -1; }else{ printf("pipe create success\n"); } close(pipe_fd[0]); close(pipe_fd[1]); } 管道的读写 选创建一个管道,通过fork()函数创建一个子进程,子进程会继承父进程所创建的管道 示例代码如下: #include <unistd.h> #include <sys/types.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> int main(){ int pipe_fd[2]; pid_t pid; char buf_r[100]; char *p_wbuf; int r_num; memset(buf_r,0,sizeof(buf_r)); /*创建管道*/ if(pipe(pipe_fd)<0){ printf("create pipe error\n"); return -1; } /*创建子进程*/ if((pid=fork())==0){//子进程中运行 printf("\n"); close(pipe_fd[1]); sleep(2); if((r_num=read(pipe_fd[0],buf_r,100))>0){ printf("%d number read form the pipe is %s\n",r_num,buf_r); } close(pipe_fd[0]); exit(0); } else if(pid>0){//父进程中运行 close(pipe_fd[0]); if(write(pipe_fd[1],"hello",5)!=-1){ printf("parent write1 hello!\n"); } if(write(pipe_fd[1]," pipe",5)!=-1){ printf("parent write2 page!\n"); } close(pipe_fd[1]); sleep(3); waitpid(pid,NULL,0); exit(0); } } 运行结果如下: [retacn@localhost tmp]$ gcc pipe_rw.c -o pipe_rw [retacn@localhost tmp]$ ./pipe_rw parent write1 hello! parent write2 page! 10 number read form the pipe is hello pipe 有名管道 用于运行于同一系统中的任意两个进程间的通信 fifo,与无命管道的区别是不相关的进程也能交换数据 建立命名管道 #include <sys/types.h> #include <sys/stat.h> int mkfifo(const char *pathname,mode_t mode) pathname:fifo文件名 mode:属性 当使用open打开fifo文件时,O_NONBLOCK会产生以下影响 使用时,访问要求无法满足时不阻塞,立即返回,errno是enxio 不使用时,访问要求无法满足时进程将阻塞 示例代码如下: fifo_read.c #include <sys/types.h> #include <sys/stat.h> #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <memory.h> #define FIFO "/home/retacn/tmp/myfifo" main(int argc,char *argv){ char buf_r[100]; int fd; int nread; /*创建管道*/ if((mkfifo(FIFO,O_CREAT|O_EXCL)<0)&&(errno!=eexist)){ printf("cannot create fifoserver\n"); } printf("preparing for reading bytes...\n"); memset(buf_r,0,sizeof(buf_r)); /*打开管道*/ fd=open(FIFO,O_RDONLY|O_NONBLOCK,0); if(fd==-1){ perror("open"); exit(1); } while(1){ memset(buf_r,0,sizeof(buf_r)); if((nread=read(fd,buf_r,100))==-1){ if(errno==EAGAIN){ printf("no data yet\n"); } } printf("read %s form fifo\n",buf_r); sleep(1); } /*暂停,等待信号*/ pause(); } fifo_write.c #include <sys/types.h> #include <sys/stat.h> #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <memory.h> #define FIFO_SERVER "/home/retacn/tmp/myfifo" main(int argc,char **argv){ int fd; char w_buf[100]; int nwrite; /*打开管道*/ fd=open(FIFO_SERVER,O_WRONLY|O_NONBLOCK,0); if(argc==1){ printf("please send sonething\n"); exit(-1); } strcpy(w_buf,argv[1]); /*向管道写入数据*/ if((nwrite=write(fd,w_buf,100))==-1){ if(errno==EAGAIN){ printf("the fifo has not been read yet,please try later\n"); } }else{ printf("write %s the fifo\n",w_buf); } }