进程间通信:多个进程之间数据相互交换。
进程间通信的方式:信号、管道(无名管道、有名管道)、信号量、消息队列、共享内存、套接字。
进程的创建:pid_t fork(void);
管道的原理:
有名管道:应用于两个进程之间数据的单向传递。
创建:命令方式:mkfifo 函数方式:mkfifo()
打开:open
写数据:write
读数据:read
关闭:close
在文件目录数中有一个文件标示(管道文件)实际不占据磁盘空间,数据缓存在内存上。
阻塞运行函数:函数调用后不会立即返回,需要等待某些条件的发生才会返回,open操作管道文件时,阻塞运行的函数。
如果一个进程以只写(读)方式打开一个管道文件,open会阻塞运行,直到有一个以读(写)方式打开管道文件,open才会返回,进程才会接着运行。
read函数也会阻塞运行,直到写端写入数据或者所有的写端都关闭,read读取数据并且会将内存上的已读数据清空。
void mian()
{
int fd = open("FIFO",O_WRONLY);
if(fd == -1)
{
exit(0);
}
printf("FIFO open success\n");
//sleep(10);
write(fd,"hello world",11);
printf("write success\n");
close(fd);
}
void main()
{
int fd = open("FIFO",O_RDONLY);
if(fd == -1)
{
exit(0);
}
printf("FIFO open success\n");
char buff[128] = {0};
read(fd,buff,127);
printf("read data:%s\n",buff);
close(fd);
}
练习:A 进程负责循环接受用户输入的数据, 以”end”为结束标志, B 进程负责统计用户输入的字母个数。
//testa 接受用户输入的数据,以end为结束标志
#include
#include
#include
#include
void main()
{
int fd = open("FIFO",O_WRONLY);
if(fd == -1)
{
exit(0);
}
while(1)
{
printf("please input:");
fflush(stdout);
char arr[128] = {0};
fgets(arr,127,stdin);
write(fd,arr,strlen(buff)-1);
if(strncmp(buff,"end",3) == 0)
{
break;
}
}
close(fd);
}
//testb 统计用户输入的字母个数
#include
#include
#include
#include
void main()
{
int fd = open("FIFO",O_RDONLY);
if(fd == -1)
{
exit(0);
}
while(1)
{
char buff[128] = {0};
int count = 0;
read(fd,buff,127);
if(strncmp(buff,"end",3) == 0)
{
break;
}
count += strlen(buff);
printf("%d\n",count);
}
}
close(fd);
}
无名管道:无名是相对于有名而言的,其在使用时产生,不使用后释放。不会在系统上留下蛛丝马迹。因为它在使用前没有任何标示,所以它只能用于父子进程之间。
创建与打开:int pipe(int fd[2]) 若成功则返回0,失败返回-1。fd[0]代表读, fd[1]代表写。
读:read(fd[]0],buff,size);
写:write(fd[1],buff,len);
关闭:close(fd[1]); close(fd[0]);
使用:int arr[2]; pipe(arr);
需要注意的是:管道都是半双工通讯, 无名管道创建后,父进程在 fork 产生子进程后,两个进程分别有一对读写,要在父子进程分别关闭读或写。
与上面相同的例题,用无名管道来做:
void main()
{
int fd[2] = {0};
pipe(fd);
pid_t pid = fork();
if(pid == 0)
{
while(1)
{
close(fd[0]);
printf("please input:");
fflush(stdout);
fgets(buff,127,stdin);
write(fd[1],buff,strlen(buff)-1);
if(strncmp(buff,"end",3) == 0)
{
break;
}
}
}
else
{
close(fd[1]);
while(1)
{
int count = 0;
read(fd[0],buff,127);
if(strncmp(buff,"end",3) == 0)
{
break;
}
count += strlen(buff);
printf("%d\n",count);
}
}
close(fd[0]);
close(fd[1]);
}