Linux系统编程|信号进阶 + SystemV IPC(消息队列、共享内存)

一、信号进阶:发送信号、pause、alarm定时器

1.1 kill() ------ 向指定进程发送信号

kill不只是杀死进程,本质功能:给指定PID的进程发送信号,可以发送任意合法信号。

头文件

#include <sys/types.h>

#include <signal.h>

int kill(pid_t pid, int sig);

参数说明

  • pid:接收信号的进程ID

  • pid > 0:信号发送给pid对应的进程

  • pid = 0:发送给当前进程组所有进程

  • pid = -1:发送给系统内有权限的全部进程

  • sig:信号编号(如`SIGINT`、`SIGUSR1`)

返回值

  • 成功返回0;失败返回1,设置errno。

示例:kill(pid, SIGKILL);强制杀死目标进程。

1.2 pause() ------ 进程休眠等待信号唤醒

#include <unistd.h>

int pause(void);

功能:将当前进程挂起休眠,直到捕获到一个信号,执行完信号处理函数之后pause才返回。

返回值:永远返回1,errno设置为EINTR,表示被信号中断。

使用场景:进程休眠等待外部信号触发业务逻辑。

注意:必须提前注册信号捕获处理函数,如果收到的信号是默认终止行为,进程直接退出,pause不会返回。

1.3 alarm() 定时信号

#include <unistd.h>

unsigned int alarm(unsigned int seconds);

功能:seconds秒之后,向自己进程发送SIGALRM信号。

  • SIGALRM默认动作:终止进程。

  • 如果多次调用alarm,新调用会覆盖上一次定时器。

返回值:返回上一次剩余倒计时秒数;之前没有设置返回0。

简单示例:

#include <stdio.h>

#include <unistd.h>

#include <signal.h>

void alarm_handler(int sig)

{

printf("收到定时SIGALRM信号!\n");

}

int main(void)

{

signal(SIGALRM, alarm_handler);

alarm(3); //3秒后发出SIGALRM

pause();

printf("程序继续往下执行\n");

return 0;

}

```

二、SystemV IPC通用知识点

2.1 ftok() 生成IPC对象key键值

SystemV IPC(消息队列、共享内存、信号量集)依靠`key_t`键值,多个进程使用同一个key,就可以访问同一个内核IPC对象。

#include <sys/types.h>

#include <sys/ipc.h>

key_t ftok(const char *pathname, int proj_id);

  • pathname:必须是真实存在的文件路径;

  • proj_id:项目ID,0255的整数;

返回值:成功返回key;失败返回1。

原理:利用文件inode + proj_id计算出唯一key;同一个文件+同一个proj_id得到的key完全相同。

2.2 IPC命令行调试工具

ipcs -a # 查看系统所有SystemV IPC对象

删除消息队列

ipcrm -q 消息队列ID

ipcrm -Q key值

删除共享内存

ipcrm -m shmid

ipcrm -M key

删除信号量集

ipcrm -s semid

ipcrm -S key

三、消息队列 Message Queue

消息队列是**内核维护的消息链表**,每条消息带有消息类型`mtype`;进程可以按照消息类型选择性读取消息,不再像管道只能读取字节流。

特点:

  1. 消息有类型字段,可以按类型筛选接收;

  2. 收发进程不需要同时运行,消息缓存在内核;

  3. 进程结束消息队列不会自动销毁,需要手动删除。

3.1 核心结构体

struct msgbuf {

long mtype; /* 消息类型,必须大于0 */

char mtext1; /* 消息正文,长度自定义 */

};

3.2 全套API

① msgget() 创建/获取消息队列ID

#include <sys/msg.h>

int msgget(key_t key, int msgflg);

  • key:ftok生成的key;

  • msgflg:IPC_CREAT | 0664,不存在则创建,存在直接获取;

返回值:成功返回消息队列ID(msqid);失败1。

② msgsnd() 发送消息

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

  • msqid:msgget返回ID;

  • msgp:指向msgbuf消息结构体;

  • msgsz:消息正文mtext字节大小,不包含mtype;

  • msgflg:填0代表阻塞发送。

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

③ msgrcv() 接收消息

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

  • msgtyp:消息类型

  • msgtyp = 0:读取队列第一条消息;

  • msgtyp >0:读取mtype等于msgtyp的消息;

  • msgflg:0阻塞读取;

返回值:成功返回读到正文字节数,失败1。

④ msgctl() 控制消息队列(删除/获取属性)

int msgctl(int msqid, int cmd, struct msqid_ds *buf);

  • cmd:IPC_RMID删除消息队列,此时buf传NULL;

  • IPC_STAT获取队列属性。

四、共享内存 Shared Memory

SystemV共享内存:Linux速度最高效的IPC通信方式。

原理:内核开辟一块物理内存,多个进程把同一块内存映射到各自用户虚拟地址;进程直接读写这块内存,**减少用户态和内核态之间的数据拷贝**。

注意:共享内存本身不带同步互斥!多进程并发读写会出现竞争,一般搭配信号量做保护。

API接口

① shmget 创建/获取共享内存ID

#include <sys/shm.h>

int shmget(key_t key, size_t size, int shmflg);

  • size:共享内存字节大小,建议4096(一页)整数倍;

  • shmflg:IPC_CREAT | 0664;

返回:成功shmid,失败1。

② shmat 映射共享内存到进程用户空间

void *shmat(int shmid, const void *shmaddr, int shmflg);

  • shmaddr:填NULL,由内核自动选择映射地址;

  • shmflg:0读写;SHM_RDONLY只读;

返回值:成功返回映射后的虚拟内存首地址;失败返回(void *)-1。

拿到返回指针,进程就可以直接读写这块内存,就像普通数组一样。

③ shmdt 解除映射

int shmdt(const void *shmaddr);

功能:解除当前进程和共享内存的映射关系。

shmdt仅仅解除映射,不会删除内核里面的共享内存对象!

④ shmctl 删除共享内存对象

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

cmd传IPC_RMID,buf填NULL,删除内核共享内存对象。

相关推荐
Zwawa5 分钟前
把 AO 接回来:黑线和白底之间到底差了多少
c语言·单片机·嵌入式
weixin199701080168 分钟前
《1688消息服务落地方案:alibaba.message.* 与 Webhook 回调的可靠性与重试策略》(附Python源码)
开发语言·python
-dzk-15 分钟前
【多维动态规划】LC 1143.最长公共子序列
算法·动态规划
ZHOUPUYU18 分钟前
PHP 9.0 前瞻:下一代 PHP 会带来哪些新功能?
android·开发语言·php
某不知名網友18 分钟前
ROS2 核心通信:话题发布与订阅详解
开发语言·c++
C++ 老炮儿的技术栈19 分钟前
char (*csConnectName)[256]; 和 char csConnectName [256] 有什么区别
java·c语言·开发语言·c++·人工智能·算法·c
人生百态,人生如梦20 分钟前
Ubuntu在低版本下使用ccswitch+claudecode(CCSwitch+Docker+Claude)连调教程
linux·ubuntu·docker·claudecode·ccswitch
Omics Pro29 分钟前
全新可重分析!代谢组质谱专用
数据库·人工智能·算法·机器学习·自然语言处理
Nebula_g30 分钟前
JavaSE加强:线程Thread(线程安全重点)
java·开发语言·jvm·算法·javase·技术栈
一只废狗狗狗狗狗狗狗狗狗31 分钟前
Network架构1——卷积神经网络CNN
人工智能·算法·cnn