进程间通信

1、为什么要进行进程间的通信呢?通信的目的?

1.实现进程间的数据传递

2.实现进程间的数据共享

3.实现进程间的事件的通知等等

2、Linux中进程间通信的方式

早期的进程间通信方式: 有名管道、无名管道、信号----------同一台主机上进程间的通信

System V IPC对象 共享内存、消息队列、信号量------同一台主机上进程间的通信

BSD: socket------不同主机上进程间的通信(网络编程中要研究)

3、无名管道

3-1、特点

《1》只能用于具有亲缘关系的进程间的通信 : 父子进程、兄弟进程

《2》半双工的通信模式,具有固定的读端和写端, 一端进行读操作,一端进行写操作

《3》管道可以看成是一种特殊的文件,对于它的读写可以使用文件IO如read、write、close函数。 注意: 无名管道不属于任何文件系统,存在于内核中

《4》无名管道在应用层角度来说,是有2个文件描述符来标识他, fd[0]表示读端 fd[1]表示写端 管道是基于文件描述符的通信方式。

当一个管道建立时,它会创建两个文件描述符fd[0]和fd[1]。其 中fd[0]固定用于读管道,而fd[1]固定用于写管道。

3-2、创建无名管道

#include

int pipe(int fd[2])

/*

参数1:保存2个文件描述符的数组

返回值:成功0, 失败 -1

*/

close(fd); //关闭

3-3、实现

子进程给无名管道写数据,父进程从无名管道中读数据

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
//创建管道
int fd[2]= {0};
int res = pipe(fd);
if(res<0)
{
perror("pipe error");
return -1;
}
//创建子进程
pid_t pid = fork();
if(pid<0)
{
perror("fork error");
return -1;
}
else if(pid ==0) //子进程 fd[0] fd[1]
{
//关闭读端
close(fd[0]);
char buf_write[256] = {0};
//给管道中写数据
fgets(buf_write, sizeof(buf_write), stdin);
write(fd[1], buf_write, sizeof(buf_write));
close(fd[1]);
}
else if(pid>0) //父进程 fd[0] fd[1]
{
//关闭写端
close(fd[1]);
char buf_read[256] = {0};
//从管道中读取数据
read(fd[0], buf_read, sizeof(buf_read));
printf("read data = %s\n", buf_read);
//关闭读端
close(fd[0]);
}
return 0;
}

3-4、无名管道的容量: 64KB

4、有名管道

对无名管道的一种优化!

无名管道只能实现具有亲缘关系的进程之间的通信!

没有亲缘关系的进程也要进行通信,需要用到有名管道!

4-1、特点

《1》无名管道只能用于具有亲缘关系的进程之间,这就限制了无名管道的使用范围

《2》有名管道可以使互不相关的两个进程互相通信。有名管道可以通过路径名来指出,并且在文件系统中可见

《3》进程通过文件IO来操作有名管道, open\read\write\close

《4》有名管道遵循先进先出规则, 从头开始读,写入的追加在尾巴处!

《5》不支持如lseek() 操作

《6》有名管道本质上就是一个文件

4-2、创建有名管道

《1》使用命令的方式创建有名管道

mkfifo myfifo 默认权限是 0664

《2》使用函数的方式创建有名管道

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *filename,mode_t mode);
/*
参数1: 有名管道的名称
参数2:权限 8进制的数表示 0777 0664
返回值: 成功0 失败 -1
*/
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
int main()
{
int res = mkfifo("./fifo_1", 0777);
if(res <0)
{
perror("mkfifo error");
return -1;
}
printf("mkfifo ok\n");
return 0;
}

4-3、实现

使用有名管道实现一下非亲缘关系的进程间的通信

写两个.c文件,分别进行编译,得到的程序去运行,就是两个没有关系的进程!

一个.c给有名管道中写数据

//写数据
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
int main()
{
//创建有名管道
int res = mkfifo("./fifo_2", 0664);
if(res<0 && errno!=EEXIST)//保证管道存在的情况下不会报错!
{
perror("mkfifo error");
return -1;
}
//打开有名管道文件
int fd = open("./fifo_2", O_WRONLY);
if(fd<0)
{
perror("open error");
return -1;
}
//写入数据
char buf_write[256] = {0};
while(1)
{
memset(buf_write, 0, sizeof(buf_write));
fgets(buf_write, sizeof(buf_write), stdin);
write(fd, buf_write, sizeof(buf_write));
}
close(fd);
return 0;
}

一个.c从有名管道中读数据

//读数据
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
int main()
{
//创建有名管道
int res = mkfifo("./fifo_2", 0664);
if(res<0 && errno!=EEXIST)
{
perror("mkfifo error");
return -1;
}
//打开有名管道文件
int fd = open("./fifo_2", O_RDONLY);
if(fd<0)
{
perror("open error");
return -1;
}
//读数据
char buf_read[256] = {0};
while(1)
{
memset(buf_read, 0, sizeof(buf_read));
read(fd, buf_read, sizeof(buf_read));
printf("read data =%s\n", buf_read);
}
close(fd);
return 0;
}

5、信号

5-1、什么是信号?

在软件层对中断机制的一种模拟,是一种异步通信方式!

5-2、特点

《1》信号可以直接进行用户空间进程和内核进程之间的交互,内核进程也可以利用它来通知用户空间进程发生了哪些系统事件。

《2》如果该进程当前并未处于执行态,则该信号就由内核保存起来,直到该进程恢复执行再传递给它;如果一个信号被进程设置为阻塞,则该信号的传递被延迟,直到其阻塞被取消时才被传递给进程。

5-3、实现

《1》使用硬件去触发信号的产生

ctrl+c 终止进程 SIGINT

ctrl+\ 终止进程 SIGQUIT

ctrl+z 暂停进程 SIGTSTP

《2》使用函数去触发信号的产生

kill函数:向另外的一个进程发信号

#include

#include

int kill(pid_t pid, int sig);

进程id

信号

raise函数: 进程向自己发送信号

#include

#include

int raise(int sig);

信号编号

alarm函数: 内核就向进程发送SIGALARM信号

#include

unsigned int alarm(unsigned int seconds)

参数1: 设置的时长,s单秒

pause函数:用于将调用进程挂起直到收到信号为止

#include

int pause(void);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值