进程间通信(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);
}
}