1,进程间通信的方式
1,管道
2,消息队列
3,共享内存
4,信号量
2.进程间通信目的:
1)数据传输:一个进程需要将它的数据发送给另一个进程
2)资源共享:多个进程之间共享同样的资源。
3)通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止 时要通知父进程)。
4)进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另 一个进程的所有陷入和异常,并能够及时知道它的状态改变
3,进程间通信发展
管道
System V进程间通信
POSIX进程间通信
4,进程间通信发展
管道
System V进程间通信
POSIX进程间通信
5,进程间通信分类
管道
匿名管道pipe
命名管道
System V IPC
System V 消息队列
System V 共享内存
System V 信号量
POSIX IPC
消息队列
共享内存
信号量
互斥量
条件变量
读写锁
进程间通信必须要看到一份公共资源,这里的资源应该属于谁?肯定是操作系统!
进程间通信的本质前提,也可能以队列的方式,也可能提供的就是原始的内存块,这也是通信方式有很多种的原因
管道
什么是管道:管道是Unix 中最古老的进程间通信的形式
我们把一个进程连接到另一个进程的一个数据流称为“管道”,为了方便我们理解如下图:
进程间通信----管道1,进程间通信的方式4,信号量2.进程间通信目的:3,进程间通信发展4,进程间通信发展管道1.读端不读或者读的慢,写段要等读端 可以看出进程要相互通信需要一块公共资源,而管道就一个共享文件,具体通信方式如下图:
进程间通信----管道1,进程间通信的方式4,信号量2.进程间通信目的:3,进程间通信发展4,进程间通信发展管道1.读端不读或者读的慢,写段要等读端
进程间通信----管道1,进程间通信的方式4,信号量2.进程间通信目的:3,进程间通信发展4,进程间通信发展管道1.读端不读或者读的慢,写段要等读端 #include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main()
{
int pipefd[2];
int ret = pipe(pipefd);
if(ret < 0)
{
perror("pipe()");
}
printf("%d\n",pipefd[0]);
printf("%d\n",pipefd[1]);
}
进程间通信----管道1,进程间通信的方式4,信号量2.进程间通信目的:3,进程间通信发展4,进程间通信发展管道1.读端不读或者读的慢,写段要等读端 接下来我们看一下父子进程正常通信的情况,子进程写,父进程读。
#include<stdio.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>
int main()
{
int pipefd[2];
int ret = pipe(pipefd);
if(ret < 0)
{
perror("pipe()");
}
printf("%d\n",pipefd[0]);
printf("%d\n",pipefd[1]);
if(fork() == 0) //子进程
{
const char* buf = "hello 天下";
close(pipefd[0]);
write(pipefd[1],buf,strlen(buf));
close(pipefd[1]);
exit(1);
}
close(pipefd[1]);
char buffer[64] = {0};
read(pipefd[0],buffer,sizeof(buffer));
printf("%s\n",buffer);
close(pipefd[0]);
int status = 0;
waitpid(-1,&status,0);
printf("exit code :%d\n",(status >> 8)& 0xFF);
printf("exit signal: %d\n",status & 0x7F);
//父进程
}
进程间通信----管道1,进程间通信的方式4,信号量2.进程间通信目的:3,进程间通信发展4,进程间通信发展管道1.读端不读或者读的慢,写段要等读端 结论:管道是一个只能单向通信的的通信管道 。
接下来我们看一下子进程一直写,父进程5秒钟读一次;
#include<stdio.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>
int main()
{
int pipefd[2];
int ret = pipe(pipefd);
if(ret < 0)
{
perror("pipe()");
}
printf("%d\n",pipefd[0]);
printf("%d\n",pipefd[1]);
if(fork() == 0) //子进程
{
while(1)
{
const char* buf = "hello 天下";
close(pipefd[0]);
write(pipefd[1],buf,strlen(buf));
}
close(pipefd[1]);
exit(1);
}
close(pipefd[1]);
while(1)
{
char buffer[64] = {0};
read(pipefd[0],buffer,sizeof(buffer));
printf("%s\n",buffer);
sleep(5);
}
close(pipefd[0]);
//int status = 0;
// waitpid(-1,&status,0);
// printf("exit code :%d\n",(status >> 8)& 0xFF);
// printf("exit signal: %d\n",status & 0x7F);
//父进程
}
进程间通信----管道1,进程间通信的方式4,信号量2.进程间通信目的:3,进程间通信发展4,进程间通信发展管道1.读端不读或者读的慢,写段要等读端 结论: 管道是面向字节流的,子进程一直写“hello 天下”,父进程5秒读一次,但不是一次读5个“hello 天下”。
我们现在看一下管道文件多大:每次写一个字符,读端不读,直到写满。
#include<stdio.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>
int main()
{
int pipefd[2];
int ret = pipe(pipefd);
if(ret < 0)
{
perror("pipe()");
}
printf("%d\n",pipefd[0]);
printf("%d\n",pipefd[1]);
if(fork() == 0) //子进程
{
int count = 0;
while(1)
{
//const char* buf = "hello 天下";
char ch = 'a';
close(pipefd[0]);
write(pipefd[1],&ch,1);
++count;
printf("%d\n",count);
}
close(pipefd[1]);
exit(1);
}
close(pipefd[1]);
while(1)
{
// char buffer[64] = {0};
// read(pipefd[0],buffer,sizeof(buffer));
// printf("%s\n",buffer);
// sleep(5);
}
close(pipefd[0]);
//int status = 0;
// waitpid(-1,&status,0);
// printf("exit code :%d\n",(status >> 8)& 0xFF);
// printf("exit signal: %d\n",status & 0x7F);
//父进程
}
进程间通信----管道1,进程间通信的方式4,信号量2.进程间通信目的:3,进程间通信发展4,进程间通信发展管道1.读端不读或者读的慢,写段要等读端 最大是 65536字符,也就是4KB.
接下来我们在看4种情况:
a.读端不读或者读的慢,写段要等读端
b.读端关闭,写端收到SIGPIPE信号直到终止
c.写端不写或者写的慢,读端要等写端
d.写端关闭,读端读完pipe内部的数据然后在读,会读到0,表示读到文件结尾
1.读端不读或者读的慢,写段要等读端
#include<stdio.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>
int main()
{
int pipefd[2];
int ret = pipe(pipefd);
if(ret < 0)
{
perror("pipe()");
}
printf("%d\n",pipefd[0]);
printf("%d\n",pipefd[1]);
if(fork() == 0) //子进程
{
int count = 0;
while(1)
{
//const char* buf = "hello 天下";
char ch = 'a';
close(pipefd[0]);
write(pipefd[1],&ch,1);
++count;
printf("%d\n",count);
}
close(pipefd[1]);
exit(1);
}
close(pipefd[1]);
while(1)
{
char buffer[64] = {0};
read(pipefd[0],buffer,sizeof(buffer));
printf("%c\n",buffer[0]);
sleep(5);
}
close(pipefd[0]);
//int status = 0;
// waitpid(-1,&status,0);
// printf("exit code :%d\n",(status >> 8)& 0xFF);
// printf("exit signal: %d\n",status & 0x7F);
//父进程
}
写端写满了,读端一次读64个字符,但是写端并没有写入
进程间通信----管道1,进程间通信的方式4,信号量2.进程间通信目的:3,进程间通信发展4,进程间通信发展管道1.读端不读或者读的慢,写段要等读端 写端写满了,读端一次读1024 * 2个字符,但是写端写入
进程间通信----管道1,进程间通信的方式4,信号量2.进程间通信目的:3,进程间通信发展4,进程间通信发展管道1.读端不读或者读的慢,写段要等读端 2.读端关闭,写端收到SIGPIPE信号直到终止
#include<stdio.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>
int main()
{
int pipefd[2];
int ret = pipe(pipefd);
if(ret < 0)
{
perror("pipe()");
}
printf("%d\n",pipefd[0]);
printf("%d\n",pipefd[1]);
if(fork() == 0) //子进程
{
int count = 0;
while(1)
{
//const char* buf = "hello 天下";
char ch = 'a';
close(pipefd[0]);
write(pipefd[1],&ch,1);
++count;
printf("%d\n",count);
}
close(pipefd[1]);
exit(1);
}
close(pipefd[1]);
while(1)
{
char buffer[1024*2] = {0};
read(pipefd[0],buffer,sizeof(buffer));
printf("%c\n",buffer[0]);
sleep(5);
close(pipefd[0]);
exit(0);
}
int status = 0;
waitpid(-1,&status,0);
printf("exit code :%d\n",(status >> 8)& 0xFF);
printf("exit signal: %d\n",status & 0x7F);
//父进程
}
进程间通信----管道1,进程间通信的方式4,信号量2.进程间通信目的:3,进程间通信发展4,进程间通信发展管道1.读端不读或者读的慢,写段要等读端
进程间通信----管道1,进程间通信的方式4,信号量2.进程间通信目的:3,进程间通信发展4,进程间通信发展管道1.读端不读或者读的慢,写段要等读端 开始子进程和父进程一直在运行,到第五秒父进程退出,此时子进程也退出。
3.写端不写或者写的慢,读端要等写端
这种情况不做演示了。这个更正常情况是一样的。
4.d.写端关闭,读端读完pipe内部的数据然后在读,会读到0,表示读到文件结尾
进程间通信----管道1,进程间通信的方式4,信号量2.进程间通信目的:3,进程间通信发展4,进程间通信发展管道1.读端不读或者读的慢,写段要等读端