进程间通信
标题进程间通信
进程间通信:>>
进程间通信:进程间的沟通交流
进程之间为什么要进行沟通交流?
在实际工作过程中往往会出现在一个系统中好几个进程协同工作,那么这些进程就需要
沟通交流
因为进程的独立性,因此进程之间的沟通交流就变得复杂,困难
因此就产生了各种进程间通信的方式,来解决进程之间的通信问题
进程间通信的发展:
管道
System V 进程间通信
POSIX 进程间通信
进程间通信的分类:
匿名管道 pipe
命名管道
通信方式:
消息队列、共享内存、信号量、互斥量、条件变量、读写锁
管道:传输资源-----“数据资源”
本质::“内核的一块缓冲区”、Linux一切皆文件、操作系统为管道提供操作的办法::文件操作:
分类::匿名管道:
命名管道:
功能:ps -ef | grep ssh将前面的输出结果给后面的输入
进程中传输的是-----数据资源
管道特性:{
1.只能用于具有亲缘关系的进程间通信
2.管道是半双工通信
3.管道的生命周期随进程
4.管道面向字节流传输数据
面向字节流: '收发数据灵活',数据无规则发送,接收灵活
5.自带同步与互斥:{
:临界资源: '大家都能访问到的公共资源比如管道就是临界资源'
,临界区: '对临界资源操作的代码操作公共资源'
********,同步: '访问的时序性'
********,互斥: '对临界资源同一时间的唯一访问性, 保护临界资源的安全'
}
};
管道读写规则:{
管道无数据: '读取'
如果描述符是默认的阻塞属性,读取将会阻塞挂起等待,直到管道有数据
如果描述符设置为非阻塞属性,读取操作将不具备条件,直接报错返回 EAGAIN
管道是内核的一块缓冲区 ,是由大小的;可能会写满; EAGAIN 描述符未准备好
如果描述符是默认的阻塞属性,写入操作将会阻塞挂起等待,直到有数据被取走
如果描述符设置为非阻塞属性,写入操作将不具备条件,直接报错返回'错误码'
如果写入段全部被关闭,这时候如果读取数据,读取完管道中的数据,然后返回0
如果读取段全部被关闭,这时候如果写入数据,则触发异常,操作系统会给进程发送 SIGPIEPE 信号,
进程收到这个信号将会退出;
原子性:
原子操作: '不会被打断,一部完成'
};
————单向通信————、半双工
****进程间通信有关函数:{ 'Z:\Linux\进程间通信\pipe.cpp,pipe1.cpp'
:pipe();
int fd[2];
'管道须在子进程创建之前创建好','这样才能进行复制'
if(pipe(fd) < 0)
{
perror("pipe error");
return -1;
}
int pid = -1;
pid = fork();
if(pid < 0)
{
return -1;
}
else if(pid == 0)
{ '子进程'
close(fd[1]);
char buffer[1024] = {0};
read(fd[0], buffer, 1024);
cout << "child:" << buffer << endl;
close(fd[0]);
}
else
{
sleep(3);
close(fd[0]);
write(fd[1], "hello", 5);
close(fd[1]);
}
命名管道:{ 'Z:\Linux\进程间通信\fifo.c'
#include<sys/stat.h>
int mkfifo(const char* pathname, mode_t mode);'创建命名管道'
pathname '管道文件的路径名'
mode '管道文件的权限'
成功 0; 失败 -1
2.打开管道:open
3.从管道读取数据 read
4.关闭管道文件 close
如果写端都关闭了则返回 0
List item
}
};
****进程间通信有关命令:{
:ps -ef | grep ssh '实现'
,ps '这个命令最终将结果打印到显示器上,然而,我们并不想让它打印到界面,而是将结果写入管道'
,grep '这个进程本身从标准输入获取数据,但是我们想的是,不要在标准输入拿数据而是从管道中读取数据
,因此将标准输入进行重定向到管道读取端'
,'因此将标准输出重定向到管道写入端'
,grep -ER 'IPE_BUF' /usr/include/ '搜索PIPE_BUF '
,mkfifo pipe_name; '创建命名管道'
};
进程间通信的本质原因: '进程的独立性'
进程要进行协作完成功能就需要进行沟通,因为进程的的独立性所以沟通变得困难
让操作系统提供进程通信的方式:
本质上为进程提供一个功能的通信媒介
因为提供的媒介方式不同,因此进程间的通信方式也就有很多
进程间的通信方式{
:管道(匿名管道,命名管道)
system V标准的进程间通信方式:{
:消息队列
,共享内存
,信号量
}
};
管道:>>{
匿名管道:
本质: '内核的一块缓冲区,即一块内存'----'操作方法即 IO '
创建的缓冲区是没有名字的: '仅用于具有亲缘关系的进程间通信'
匿名管道的创建: pipe(int fd[2])
创建成功后会返回两个文件描述符:供我们对管道进行操作,
这个操作就是我们的 IO 操作
:fd[0]: 用于读取数据
,fd[1]: 用于写入数据
,匿名管道的原理:其实就是创建一个子进程
,子进程复制了父进程的描述符表
,因此也有两个描述符
,并且他们指向同一个管道.这时候因为他们里昂个都能访问到这个管道
,因此他们就可以进行通信了
只不过管道是半双工通信,因此在通信之间需要确定数据流向
如何确定数据流向呢?
就是关闭父子进程各自一端读写,如果只读就关闭写的描述符
命名管道: 文件系统可见 '本机上的任意进程','不仅仅局限于父子进程---具有亲缘关系的进程'
test.fifo 命名管道文件
创建:
1.命名创建:mkfifo pipe_name
2.代码创建:
int mkfifo(const char* pathname, mode_t mode);
};
进程间通信:进程间通信