进程间通信(IPC – InterProcess Communication)
通信的方式有很多: 文件, 管道, 信号, 共享内存, 消息队列, 套接字, 命名管道等等;
- 但是由于设计缺陷现在常用的有:
1.管道(简单, 默认匿名管道, 还有有名管道)
2.信号(开销小, 但是如果不是做系统编程一般不用, 因为缺点大于有点, 比如有没有收到无法确认)
3.共享映射区(无血缘关系之间)
4.本地套接字(最稳定)
二、 管道(有名管道, fifo)
- 特点: 相当于一个伪文件, 也是是用内核缓冲区, 也是队列实现, 也是只能读取一次, 对其进行读写操作时也是阻塞
- 使用场景: 弥补pipe, 可以完成无血缘关系的进程间通信.
- 创建方式:
1. 命令 mkfifo 文件名; 该文件不管怎么对其操作, 都不会改变其大小, 一直是0;
2. 通过 int mkfifo(const char *pathname, mode_t mode); 在第三章, 使用命令: man 3 mkfifo查看 - 使用: 即当成普通文件进行操作, open/close, read/write, unlink; 但是不能使用lseek对读写指针进行操作, 因为破坏了fifo规则
1. 创建 a.c和b.c, 以及fifo文件
2. a.c中 open — 读方式打开, 进行读操作, 然后关闭
3. b.c中open — 写方式打开, 进行写操作, 然后关闭 - 示例代码:
写端程序代码:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
int main(int argc, const char* argv[])
{
if(argc < 2)
{
printf("./a.out fifoname\n");
exit(1);
}
// 判断文件是否存在
int ret = access(argv[1], F_OK);
if(ret == -1)
{
int r = mkfifo(argv[1], 0664);
if(r == -1)
{
perror("mkfifo error");
exit(1);
}
printf("有名管道%s创建成功\n", argv[1]);
}
int fd = open(argv[1], O_WRONLY);
if(fd == -1)
{
perror("open error");
exit(1);
}
char *p = "hello, world";
while(1)
{
sleep(1);
int len = write(fd, p, strlen(p)+1);
}
close(fd);
return 0;
}
读端程序代码:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
int main(int argc, const char* argv[])
{
if(argc < 2)
{
printf("./a.out fifoname\n");
exit(1);
}
// 判断文件是否存在
int ret = access(argv[1], F_OK);
if(ret == -1)
{
int r = mkfifo(argv[1], 0664);
if(r == -1)
{
perror("mkfifo error");
exit(1);
}
printf("有名管道%s创建成功\n", argv[1]);
}
int fd = open(argv[1], O_RDWR);
if(fd == -1)
{
perror("open error");
exit(1);
}
char buf[512];
while(1)
{
int len = read(fd, buf, sizeof(buf));
buf[len] = 0;
printf("buf = %s\n, len = %d", buf, len);//在此打印len证明该管道也是阻塞的
}
close(fd);
return 0;
}