【回眸】技术干货——Linux 内核 (十五)进程间通讯 之 信号量
前言
上一篇文章介绍的共享内存有局限性,如:同步与互斥问题、内存管理复杂性问题、数据结构限制问题、可移植性差问题、调试困难问题。本篇博文介绍的信号量能够解决第一个同步与互斥问题。
信号量概念
信号量本质上是一个计数器(不设置全局变量是因为进程间是相互独立的,而这不一定能看到,看到也不能保证++引用计数为原子操作),用于多进程对共享数据对象的读取,它和管道有所不同,它不以传送数据为主要目的,它主要是用来保护共享资源(信号量也属于临界资源),使得资源在一个时刻只有一个进程独享,解决了互斥问题。
信号量常用API
1.创建/获取一个信号量
#include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> //创建/获取一个信号量,成功返回信号量ID,失败返回-1 int semget(key_t key, int nsems, int semflg);
2.改变信号量的值
#include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> //成功返回0,失败返回-1 int semop(int semid, struct sembuf *sops, size_t nsops); struct sembuf{ short sem_num; //除非使用一组信号量,否则它为0 short sem_op; //信号量在一次操作中需要改变的数据,通常是两个数,一个是-1,即P(等待)操作, //一个是+1,即V(发送信号)操作。 short sem_flg; //通常为SEM_UNDO,使操作系统跟踪信号, //并在进程没有释放该信号量而终止时,操作系统释放信号量 };
3. 控制信号量
#include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> //成功返回非0值,失败返回-1 int semctl(int semid, int semnum, int cmd, ...); union semun { int val; /* Value for SETVAL */ struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ unsigned short *array; /* Array for GETALL, SETALL */ struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */ };
信号量函数调用
comm9.c(接收操作)
#include <signal.h> #include <stdio.h> #include <sys/types.h> #include <unistd.h> //int sigaction(int signum, const struct signaction *act, struct sigaction *oldact); void handler(int signum, siginfo_t *info,void *context){ printf("get signum %d\n",signum); if (context != NULL){ printf("get data = %d\n",info->si_int); printf("get data = %d\n",info->si_value.sival_int); printf("from = %d\n",info->si_pid); } } int main(){ struct sigaction act; printf("pid = %d\n",getpid()); act.sa_sigaction = handler; act.sa_flags = SA_SIGINFO; sigaction(SIGUSR1,&act,NULL); while (1); return 0; }
comm10.c(发送操作)
#include <stdio.h> #include <signal.h> #include <sys/types.h> #include <unistd.h> #include <stdlib.h> // int sigqueue(pid_t pid, int sig,const union sigval value); int main(int argc,char **argv){ int signum; int pid; signum = atoi(argv[1]); pid = atoi(argv[2]); union sigval value; value.sival_int = 100; sigqueue(pid, signum,value); printf("pid = %d,done.\n",getpid()); return 0; }
运行结果展示
注意:这里编译完后,需要先运行comm9.c(接收)后运行comm10.c(发送)
后记碎碎念
Linux内核是一个系列,可以点击专栏查看同系列的其他文章,希望能帮到屏幕前的每一位应届生往届生,该博文最初发表在CSDN上。
#校招求职有谈薪空间吗##找工作前vs找工作后的心路变化##租房前辈的忠告##职场中你干过哪些“蠢”事##26届秋招投递记录#应届生必学实用物联网技术 文章被收录于专栏
本专栏助应届生从物联网小白成长为企业争抢的技术人才,聚焦三大核心技术:传感器应用(环境监测)、嵌入式开发(STM32/Arduino)、通信协议(LoRa/NB-IoT/MQTT),配合10+实战项目(如智能温湿度监控系统)积累项目经验。覆盖智能硬件、工业物联网、智能家居领域岗位需求,解析企业招聘技术重点与面试题,帮电子、计算机、自动化等专业学生构建知识体系,提前锁定名企Offer!