进程间通信(ipc)
- 数据传输
- 资源共享
- 时间通知
- 进程控制
linux系统下的进程通信
-
早起unix系统ipc
- 管道:无名管道 、有名管道
- 信号
- fifo
-
system-v ipc
- system-v 消息队列
- system-v 信号量
- system-v 共享内存
-
socket ipc
-
posix ipc
- posix 消息队列
- posix 信号量
- posix 共享内存
无名管道
pipefd数组 pipefd[0] 是读描述符 pipefd[1]是写描述符
- 无名管道只能局限于父子进程间的通信
- 特点:
- 特殊的文件(没有名字),无法用open,但能甩close
- 只能通过子进程继承文件描述符来使用
- write和read操可能会阻塞进程
- 所有文件描述符被关闭后,无名管道被销毁
步骤
- 父进程pipe无名管道
- fork子进程
- close无用端口
- write/read读写端口
- close读写端口
#include<stdio.h>
#include<sys/wait.h>
#include <unistd.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include<fcntl.h>
#include <string.h>
int main()
{
int pipefd[2];
pid_t pid;
int real_read,real_write;
char buf[20];
const char *data = "hello pipe\r\n";
if(pipe(pipefd) < 0)
{
perror("pipe");
exit(1);
}
if((pid = fork()) < 0)
{
perror("fork");
exit(1);
}
else if(pid == 0)
{
close(pipefd[1]);
if((real_read = read(pipefd[0],buf,sizeof(buf))) > 0)
{
printf("child:%d bytes read form pipe : %s\r\n",real_read,buf);
}
close(pipefd[0]);
exit(0);
}
else
{
close(pipefd[0]);
if((real_write = write(pipefd[1],data,strlen(data))) > 0)
{
printf("patern: %d bytes write to pipe : %s",real_write,data);
}
close(pipefd[1]);
exit(0);
}
return 0;
}
有名管道
-
mkfifo()成功返回0 失败返回1
-
特点
- 有文件名,可以用open打开
- 任意进程间数据传输
- write和read可能会阻塞进程(read时,有数据则读出,无则等待;write时管道内若已被写满,则等待)
- write具有原子性(有名管道,往管道内写数据时,先判断管道内的缓冲区是否能一次性存储要写入的数据,可以则写入数据,否则不写入数据,所以要么一次性全部写入数据,要么不写入数据,称之为原子性;无名管道,管道内还有空间,就继续写入,填满为止,故没有原子性)
-
第一个进程mkfifo有名管道
-
open有名管道,write和read数据
-
close有名管道
-
第二个进程open有名管道,write和read数据
-
close有名管道
例子
fifo_write.c
#include<stdio.h>
#include<sys/wait.h>
#include <unistd.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include<fcntl.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#define MYFIFO "/home/wzt/Code/system_programming/part_7/namedpipe_read/myfifo"
#define MAX_BUFFER_SIZE 4096
int main(int argc, char **argv)
{
int fd;
char buf[MAX_BUFFER_SIZE];
int real_write;
if(argc <= 1)
{
printf("usage:./fifp_write string\r\n");
exit(0);
}
else
{
char *pbuf = buf;
memset(pbuf, 0, MAX_BUFFER_SIZE);
for(int i=1;i<argc;i++)
{
int len = strlen(argv[i])+1;
if( (MAX_BUFFER_SIZE-(pbuf - buf)) > len)
{
sprintf(pbuf,"%s ",argv[i]);
pbuf +=len;
}
else
break;
}
}
if(access(MYFIFO,F_OK) < 0)
{
if((mkfifo(MYFIFO, 0666)<0) && (errno != EEXIST))
{
printf("Cannot create fifo file\r\n");
exit(1);
}
}
fd = open(MYFIFO,O_WRONLY);
if(fd < 0)
{
printf("open fifo file error\r\n");
exit(1);
}
if((real_write = write(fd, buf, strlen(buf))) > 0)
{
printf("write : %s to fifo \r\n",buf);
}
close(fd);
return 0;
}
fifo_read.c
#include<stdio.h>
#include<sys/wait.h>
#include <unistd.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include<fcntl.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#define MYFIFO "/home/wzt/Code/system_programming/part_7/namedpipe_read/myfifo"
#define MAX_BUFFER_SIZE 4096//PIPE_BUF
int main(int argc, char **argv)
{
char buf[MAX_BUFFER_SIZE];
int fd;
int real_read;
if(access(MYFIFO,F_OK) < 0)
{
if((mkfifo(MYFIFO, 0666)<0) && (errno != EEXIST))
{
printf("Cannot create fifo file\r\n");
exit(1);
}
}
fd = open(MYFIFO,O_RDONLY);
if(fd < 0)
{
printf("open fifo eerror\r\n");
exit(1);
}
while(1)
{
memset(buf, 0, MAX_BUFFER_SIZE);
if((real_read = read(fd,buf,MAX_BUFFER_SIZE)) > 0)
{
printf("read: %s from fifo\r\n",buf);
}
}
close(fd);
return 0;
}