进程间的通信方式(IPC)

原理

进程跑在系统之上,他们可以看到同一个系统,那么可以在系统上开辟一个共享区域,让两个进程都可以访问,即可进行通信

方法

常用的方法主要有三种:管道,共享内存以及信号。
1.管道 pipe:就是一个特殊的共享文件;管道分为两类:无名管道和有名管道
特点:单向通信,FIFO结构;双向通信的话就使用两个管道
2.共享内存:在系统中创建一片共享的内存空间,多个进程都可以看到该空间,那么他们之间就可以直接通信了
优点:没有数据拷贝,双向通信
3.信号signal:Linux进程支持信号的操作:进程在执行过程中,如果收到信号,进程会放下手中的任务,转而去执行信号处理的任务,完毕之后返回之前的位置继续执行。

管道

管道是一个特殊的文件,具有以下特征
1.文件存在于内存中,不存在于硬盘(速度快,断电数据丢失)
2.文件有固定大小(4KB)
4.读写特性:数据读走即被删除,如果读取的时候发现没有数据,read函数阻塞等待(直到有数据);如果write数据过多,buf写满,则write也会阻塞等待,直到read将数据读走删除数据。

步骤

1.创建管道,pipe:
用mkfifo函数创建
头文件:
#include <sys/types.h>
#include <sys/stat.h>
函数用法:
int mkfifo(const char *pathname, mode_t mode);
pathname:文件路径,一般选在/tmp/xxx
mode:权限 0666
返回值:成功,返回0;失败返回-1,通过perror查看失败原因
2.打开管道,open
3.write/read(读写数据)
4.关闭文件:close
5.删除管道:unlink

共享内存

步骤

1.在内存中创建一个共享内存
用shmget函数:share memory get
头文件:
#include <sys/ipc.h>
#include <sys/shm.h>
函数用法:
int shmget(key_t key, size_t size, int shmflg);
key:创建该共享内存的幻数,多个进程要共享必须使用同一个幻数
size:共享内存的大小,一般为4k,8k,12k,16k等
shmflg:访问的权限,一般为0666,0666并没有要求去创建该内存,只是在系统中寻找同key的内存;如果想去创建,可用shmflg | IPC_CREAT,表示如果有,就直接访问,没有就会创建
返回值:成功,返回的是一个内存描述符,以后通过该描述符来访问共享内存
失败,-1;可通过perror来打印错误原因

2.进程通过映射,获取共享内存的地址
用shmat函数,share memory attach,绑定
头文件:
#include <sys/types.h>
#include <sys/shm.h>
函数用法:
void *shmat( int shmid , const void * shmaddr , int shmflg)
shmid:内存描述符,它代表了一片内存空间
shmaddr:进程可以指定一个地址,映射到该内存,如果为NULL,那么系统会自动分配地址
shmflg:这次attach你想如何使用内存,如可读可写用0666等
返回值:成功,返回一个可以反问这个空间的指针
失败,返回(void *) -1;可通过perror来打印错误原因

3.通过访问该地址,就可以读写该空间

4.断开指针的空间映射关系
用shmdt函数,share memory detach,解绑
头文件:
#include <sys/types.h>
#include <sys/shm.h>
函数用法:
int shmdt( void *p)
p:就是指向那片空间的指针
返回值:成功,返回0;
失败,返回-1;可通过perror来打印失败原因

5.删除该空间
用shmctl函数,share memory control;该函数是个杂项函数,即有不同的功能
头文件:
#include <sys/ipc.h>
#include <sys/shm.h>
函数用法:
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
shimid:共享内存描述符
cmd:cmd取值不同,表示此次要实现的功能不同
IPC_STAT,获取共享内存的状态
IPC_SET,设置共享内存的状态
IPC_RMID,删除当前的共享内存
buf:表示获取/设置共享内存需要的参数;但是删除不需要任何参数,置为NULL即可
返回值:成功,返回0;
失败返回-1,可通过perror查看失败原因

信号

Linux系统中有很多种信号,每一种信号都有一个ID
kill -l:该命令可以查看信号的种类
常用的信号:2 SIGINT 在终端输入ctrl+c,终端会向进程发送SIGINT,进程会转向执行信号处理,信号处理函数(自杀即终止)

发送信号的方式

1.快捷键:例如:ctrl+c ctrl+z
2.命令:kill - 信号id 进程pid 如:kill - 9 23595
3.函数:kill(pid,signum)
头文件:
#include <sys/types.h>
#include <signal.h>
函数用法:int kill(pid_t pid, int sig);
pid:进程描述符
sig:信号id
返回值:成功,则返回0;
失败返回-1,可通过perror打印失败原因

信号的几种常见应用

1.给子进程收尸
之前父进程是调用wait函数来等子进程退出,会造成父进程阻塞。这里运用信号,当子进程要死亡的时候,给父进程发送信号,就不会造成父进程阻塞
2.应用定时器
原理:进程如果可以定时的收到信号,进程就可以定时的处理信号了
alarm()函数:请求操作系统,在未来某个时刻发送信号;比如alarm(3):在三秒后发送SIGALARM信号
3.守护进程:进程需要在后台运行,一直运行;但是当终端关闭,程序也会挂掉:因为终端关闭时会向所有子进程发送SIGHUP信号,子进程收到后会自杀。所以,要想子进程一直运行,就需要捕捉该信号
方法1:修改程序,让他可以捕捉信号
方法2:nohup ./a.out 使用nohup命令执行该程序,则该程序就会忽略SIGHUP信号

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值