进程间通信

来源:互联网 发布:北京行知实践园作文 编辑:程序博客网 时间:2024/06/02 05:16
进程间通信
(1)IPC通信分类:
  • 管道
  • 消息队列

  • 信号量
  • 共享内存
  • 套接字



(2)IPC过程:
  • 向内核申请创建IPC结构
  • 通过向内核获取IPC结构
  • 通信
  • 释放资源
管道:传递数据是单向性的,只适用于亲缘关系的进程,如父子进程,兄弟进程。创建管道时,系统为管道分配一页作数据缓冲区,进程一个只读一个只写。读在缓存区头部,写在缓存区尾部。

一 无名管道
  • 适用范围:父子进程
  • 头文件:#include <unistd.h>
  • int pipe(int fd【2】);
  • 参数:返回两个文件描述符
  • fd【0】 读
  • fd【1】写
  • 返回值:成功返回0,失败-1;
调用 pipe 函数时在内核中开辟一块缓冲区(称为管道)用于通信,它有一个读端一个写端
  通信步骤:
  1.   父进程调用pipe开辟管道,得到文件描述符指向管道两端。
  2.   父进程调用fork创建子进程,子进程得到两个文件描述符指向同一管道。
  3.   父进程关闭管道读端,子进程关闭管道写端。管道是用环形队列实现的,数据从写端流入从读端流出。
代码:
int main()
{
int fd[2]; /*创建2个元素int 数组*/
pipe(fd); /*初始化数组元素为管道文件描述符*/
int pid = fork();
if (pid > 0) /*父进程*/
{
close(fd[0]);/*关闭写端*/
for (int i = 100; i <= 150; ++i)
{
write(fd[1], &i, sizeof(int));
sleep(1);
}
close(fd[1]);
exit(0);
}
else /*子进程读*/
{
close(fd[1]); /*关闭写端*/
int x = 0;
for (int i = 0; i < 50; ++i)
{
read(fd[0], &x, sizeof(int));
printf("%d", x);
fflush(stdout);
}
close(fd[0]);
}
}

管道的局限性
  • 生命周期是随进程结束而完结
  • 只能用于具有亲缘关系的进程通信
  • 管道是匿名的,没有名字
为了克服管道上述的局限性,可以使用命名管道(Named Pipe)
二 有名管道
,函数原型是:
  • int mkfifo (const char *__path, __mode_t __mode)
  • 功能:创建新的带命名路径的FIFO
  • 参数:path — 命名管道路径
  • mode — 模式权限
  • 返回值:成功返回0,失败返回-1。
fifo文件特点:
先进先出:即写文件从有名管道数据尾端写入,数据读取从有名管道的开始处读取
注:有名管道内数据不支持如lseek()文件定位操作
对于读进程
  •若该管道是阻塞打开,且当前FIFO内没有数据,则对读进程而言将一直阻塞到有数据写入
  •若该管道是非阻塞打开,则不论FIFO内是否有数据,读进程都会立即执行读操作。即如果FIFO 内没有数据,则读函数将立刻返回0
对于写进程
  •若该管道是阻塞打开,则写操作将一直阻塞到数据可以被写入
  •若该管道是非阻塞打开而不能写入全部数据,则读操作进行部分写入或者调用失败
代码:
pipe1.c
#include<stdio.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<stdlib.h>
#include<fcntl.h>

int main()
{
if (mkfifo("pipe", 0666) < 0) /*创建管道文件*/
{
perror("pipe file create failed\n");
exit(-1);
}
int fd = open("pipe", O_WRONLY); /*打开管道*/
if (-1 == fd)
{
perror("pipe open failed\n");
exit(-1);
}
for (int i = 100; i < 150; ++i) /*进行读写*/
{
write(fd, &i, sizeof(i));
printf("%d\n", i);
sleep(1);
}

close(fd); /*关闭管道*/
unlink("pipe"); /*删除管道文件*/
}
pipe2.c
#include<stdio.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<stdlib.h>
#include<fcntl.h>

int main()
{
int fd = open("pipe", O_RDONLY); /*打开管道文件*/
if (-1 == fd)
{
perror("pipe open failed\n");
exit(-1);
}
int x; /*进行读写*/
for (int i = 0; i < 50; ++i)
{
read(fd, &x, sizeoff(int));
printf("%d", x);
fflush(stdout);
}
close(fd); /*关闭管道*/
}
运行结果:
gcc pipe2.c
./a.out
100 101 102 103 104 105 106 107 108 109
110 111 112 113 114 115 116 117 118 119
120 121 122 123 124 125 126 127 128 129
130 131 132 133 134 135 136 137 138 139
140 141 142 143 144 145 146 147 148 149

谢谢大家参考和指正,由于是自学的东西总结的,所以也许有不对的地方,望见谅。

链接:http://note.youdao.com/noteshare?id=06a92da90d37173492f5e44109735528

原创粉丝点击