进程通信的五个种类

本文详细介绍了Linux中进程间通信的五种方式:管道(包括无名管道和有名管道FIFO)、信号、共享内存、消息队列和信号量。分别阐述了每种通信方式的工作原理、使用方法及示例,帮助读者理解如何在不同场景下选择合适的进程通信机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一进程通信概述

1为什么进程间需要通信
(1)数据传输;--一个进程需要它的数据发送给另一个进程。
(2)资源共享;----多个进程之间共享同样的资源
(3)通知事件;----一个进程需要向另一个或一组发送信息,通知它们发生了某种事件。
(4)进程控制------有些进程希望完全控制另一个进程的执行
2
linux使用的进程间通信方式包括:
管道和有名管道FIFO
信号(signal)
消息队列
共享内存
信号量
3
linux使用存在每个进程task_struct结构中的信息实现信号机制,它支持的信号数受限于处理器的字长。
处理器的字长-----CPU的字长通常是指CPU内部数据总线宽度或位数。
4
linux支持最早在UNIX system V中出现三种进程间通信,它们是信息队列、信息量和共享存储器。

二管道通信

1
管道是单向的、先进先出的;写进程在管道尾部写入数据,读进程从管道的头部读出数据。
2
管道分无名管道和有名管道。
前者用于父子进程间通信;后者运行于同一系统中的任意两个进程间的通信。
3
无名管道

由pipe()函数创建
int pipe(int filedis[2])
filedis[0]用于读管道--头部;filedis[1]用于写管道--尾部。
4
管道关闭close
5
管道通信程序:
....
6
注意事项:必须在系统调用fork前调用pipe,否则子进程将不会继承文件描述符。
7
实例演练:pipe_rw.c
....
8
pid=0,则下面对应的是在进程中完成
pid>0,则在父进程中完成。

9
命名管道(FIFO)
10
创建
int mkfifo(const char*pathname,mode_t mode)
11
O_NONBLOCK
没使用。。,访问要求无法满足,进程将阻塞。
使用。。。,访问要求无法满足,进程不阻塞,立刻出错返回。errno是ENXIO。

 

三信号通信

1忽略此信号,但SIGKILL和SIGSTOP不能被忽略

2
执行用户希望的动作
3
执行系统默认的动作
对于大多数信号的系统默认动作是终止该进程

4
kill:能给自身发生信号,也可以向其他进程发送信号。
raise:向进程自身发生信号。


ps aux //查看当前进程进程号
发送
kill -s SIGQUIT 3687
给哪个PID发,用S指定

5
alarm函数可以设置一个时间值(闹钟时间),当所设置的时间到了时,产生SIGALRM信号
unsigned int alarm(unsigned int seconds)
6
paue函数:使调用进程挂起直至捕捉到一个信号。
7
信号处理
signal:是一个函数指针,有返回类型返回参数
SIG_IGN:忽略此信号
SIG_DFL:按系统默认方式处理
信号处理函数名:使用该函数处理
8
程序:mysignal.c

四共享内存

1
共享内存实现分为两步:
(1)创建共享内存,使用shmget函数
(2)映射共享内存,将这段创建的共享内存映射到具体的进程空去,使用shmat。

2
int shmget(key_t key,int size,int shmflg)
key标志共享内存的键值:0/IPC_PRIVATE.
当key取后者时,函数shmget将创建一块新的内存。如果key取0,而第三个参数又设置IPC_PRIVATE这个标志,则同样创建一块新的共享内存。
3
int shmat(int shmid,char*shmaddr,int flag)
shmid:函数返回共享存储标志符
shmaddr:赋值0,系统帮你制定个地址
flag:决定以什么方式来确定映射的地址,通常为0
返回值:
如果成功返回共享内存映射到进程中的地址,如果失败,则返回-1
4
当一个进程不再需要共享内存时,需要把它从进程地址空间中脱离。
int shmdt(char*shmaddr)

五消息队列

1
消息队列就是一个消息的链表。可以把消息看作一个记录,具有特定的格式。
2
消息队列和管道有点相似,你把数据读走后,它不在存在。
管道则只能传送无格式的字节流。
3
两种:POSIX消息队列和系统V消息队列
POSIX可移植的操作系统接口
4
消息队列随内核持续。
int msgget(key_t key,int msgflg)
5
msgflg:标志位可以取如下:
IPC_CREAT:创建新的消息队列
IPC_EXCL:与IPC_CREAT一同使用,表示如果要创建的消息队列已经存在,则返回错误
IPC_NOWAIT:读写消息队列要无法得到满足时,不阻塞。
6

key_t ftok(char*pathname,char proj)//文件名,项目名

返回文件名对应的键值

int msgget(key_t key,int msgflg)

返回与键值key相对应的消息队列描述字。

 

两种情况下,将创建一个新的消息队列
(1)msgflg:包含IPC_CREAT标志位
(2)key参数为IPC_PRIVATE。
7
发送消息的函数
int msgsnd(int msqid,struct msgbuf*msgp,int msgsz,int msgflg)
参数描述
msqid:已打开的消息队列id
msgp:存放消息的结构
msgsz:消息数据长度
msgflg:发送标志,有意义的msgflg标志为IPC_NOWAIT,指明在消息队列没有足够空间容纳要发送的消息时,msgsnd是否等待。
8
消息格式
struct msgbuf
{
 long mtype;//消息类型>0,类型只能有一个,收发都用通一个类型
 char data[255];//数据
}

9
接收消息
int msgrcv(int msgid,struct msgbuf*msgp,int msgsz,long msgtyp,int msgflg)
从msqid代表的消息队列中读取一个msgtyp类型的消息,并把消息存储在msgp指向的msgbuf结构中。在成功地读取了一个消息以后,队列中的这条消息被删除。

消息取出后放在qbuf所指向的位置。
10
%x
%p指针所指的地址
%h
11
一个类型里有多个消息

六信号量

 

1
信号量:主要用途是:进程间的控制,比如说控制互斥同步,保护临界资源,控制进程按一定的先后顺序执行
2
除用于访问控制外,还可用于进程同步。
3
二值信号灯:只能取0或1,类似于互斥锁。
但两者不同:信号灯强调共享资源,只有共享资源可用,其他进程同样可修改信号灯的值。

计数信号灯:信号灯的值可以取任意非负值。
4
创建/打开
int semget(key_t key,int nsems,int semflg)
key :键值,由ftok获得
nsems:指定打开或者新创建的信号灯集中将包含信号灯的数目
semflg:标志,同信息队列。
5
操作
int semop(int semid,struct sembuf*sops,unsigned nsops)
对信号量进行控制
semid:信号量集的ID
sops:是一个操作数组,表明进行什么操作
nsops:sops所指向的数组的元素个数
6
IPC_NOWAIT:对信号的操作不能满足时,semop()不会阻塞,并立即返回
IPC_UNDO:程序结束时释放信号量,避免结束时未将锁定的资源解锁,造成该资源永远锁定。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值