Linux--信号量

一、信号量
信号量 (semaphore)与已经介绍过的IPC结构不同,他是一个计数器。

用于实现进程间的互斥与同步,而不是用于存储进程间的通信数据。

可以与共享内存配合使用。
临界资源: 多道程序系统种存在许多进程,他们共享各种资源,然而有很多资源一次智能供一个进程使用。一次仅允许一个进程使用 的资源称为临界资源。许多物理设备都属于临界资源,如输入机、打印机、磁带机等。
信号量集: 相当于信号量的集合。
P V 操作 P拿取,V放回

1、特点:

①、信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。

②、信号量基于操作系统的PV操作,程序对信号量的操作都是原子操作。

③、每次对信号量的PV操作不仅限于对信号量加 1 或减 1 ,而且可以加减任意正整数。

④、支持信号量组

2、原型:

Linux下信号量函数都是在通用的信号量数组上进行操作,而不是在一个单一的二值信号量上进行操作。

c 复制代码
#include <sys/sem.h>
 
//创建或获取一个信号量组:若成功返回信号量级ID,失败返回-1
int semget(key_t key, int num_sems, int sem_flags);
//对信号量组进行操作,改变信号量的值:成功返回0,失败返回-1
int semop(int semid, struct sembuf semoparray[], size_t numops); 
//3.控制信号量的相关信息
int semctl(int semid, int sem_num, int cmd, ...);

3、例:

c 复制代码
//信号量

/*
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
 
//       int semget(key_t key, int nsems, int semflg);
//       int semctl(int semid, int semnum, int cmd, ...);

struct sembuf
{
    short sem_num;
    short sem_op;
    short sem_flg;
}

*/

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>

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)*/
};

int main(int argc,char const *argv[])
{
	key_t key;
	int semid;
	
	key = ftok(".",2);
	
	semid = semget(key,1,IPC_CREAT|0666);
	//获取信号量(信号量中有一个合集)
	
	//定义一个联合体
	union semun initsem;
	initsem.val = 1;
	
	semctl(semid,0,SATVAL,initsem);
	//做初始化信号量,操作第0个信号量,SATVAL设置信号量的值为initsem,


	int pid = fork();
	if(pid > 0){
		printf("this is father\n");
	}
	else if(pid == 0){
		printf("this is child\n");
	}
	else{
		printf("fork error\n");
	}
	return 0;
}

此程序运行一般为父进程先运行,然后运行子进程。偶尔反转。

修改程序,使信号量控制让子进程先运行:

c 复制代码
//修改程序,使信号量控制让子进程先运行:封装两个函数 P操作和 V操作

/*
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
 
//       int semget(key_t key, int nsems, int semflg);
//       int semctl(int semid, int semnum, int cmd, ...);
//		 int semop(int semid, struct sembuf *sops, unsigned nsops); 
struct sembuf short;
{
    short.sem_num;
    short.sem_op;
    short.sem_flg;
}

*/

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>

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)*/
};

//P操作
void pGetKey(int id)
{
	struct sembuf set;

    set.sem_num = 0;
    set.sem_op = -1;
    set.sem_flg = SEM_UNDO;
	semop(id,&set,1);
	printf("get ket!\n");
}


//V操作
void vPutBackKey(int id)
{
	struct sembuf set;

    set.sem_num = 0;
    set.sem_op = -1;
    set.sem_flg = SEM_UNDO;
	semop(id,&set,1);
	printf("put back ket!\n");
}

int main(int argc,char const *argv[])
{
	key_t key;
	int semid;
	
	key = ftok(".",2);
	
	semid = semget(key,1,IPC_CREAT|0666);
	//获取信号量(信号量中有一个合集)
	
	//定义一个联合体
	union semun initsem;
	initsem.val = 0;
	
	semctl(semid,0,SATVAL,initsem);
	//做初始化信号量,操作第0个信号量,SATVAL设置信号量的值为initsem,


	int pid = fork();
	if(pid > 0){
		pGetKey(ssemid);
		printf("this is father\n");
		vPutBackKey(semid);
		semctl(semid,0,IPC_RMID);//销毁信号量
	}
	else if(pid == 0){
		
		printf("this is child\n");
		vPutBackKey(semid);
	}
	else{
		printf("fork error\n");
	}

	return 0;
}
相关推荐
晚枫歌F3 小时前
Dpdk介绍
linux·服务器
じ☆冷颜〃4 小时前
黎曼几何驱动的算法与系统设计:理论、实践与跨领域应用
笔记·python·深度学习·网络协议·算法·机器学习
数据大魔方4 小时前
【期货量化实战】日内动量策略:顺势而为的短线交易法(Python源码)
开发语言·数据库·python·mysql·算法·github·程序员创富
POLITE34 小时前
Leetcode 23. 合并 K 个升序链表 (Day 12)
算法·leetcode·链表
TH_14 小时前
35、AI自动化技术与职业变革探讨
运维·人工智能·自动化
楚来客4 小时前
AI基础概念之八:Transformer算法通俗解析
人工智能·算法·transformer
Echo_NGC22375 小时前
【神经视频编解码NVC】传统神经视频编解码完全指南:从零读懂 AI 视频压缩的基石
人工智能·深度学习·算法·机器学习·视频编解码
会员果汁5 小时前
leetcode-动态规划-买卖股票
算法·leetcode·动态规划
橘颂TA5 小时前
【剑斩OFFER】算法的暴力美学——二进制求和
算法·leetcode·哈希算法·散列表·结构与算法
yuhaiqun19896 小时前
学服务器训练AI模型:5步路径助力高效入门
运维·服务器·人工智能·笔记·机器学习·ai