Linux System V信號量(互斥操作)

System V信號量:

System V信號量與System V其他兩種通信機制(消息隊列、共享內存)不同,其用來實現同步、互斥進程動作,通過semget函數創建一個信號集或打開一個信號量集,信號集又包括多個信號量,信號量的值要大於等於0,小於0,就會阻塞。

信號量pv操作:

p操作:操作當前信號量減去某個值
v操作:操作當前信號量加上某個值

一 . semget函數(創建信號量集):

int semget(key_t key, int nsems, int semflg)

1 . key : IPC key
2 .nsems : 信號量個數
3 . semgflg : 信號量集權限

二 . semctl函數(信號量控制):

int semctl(int semid, int semnum, int cmd, union semun arg)

1 .semid:爲信號量集標識符
2.semnum:爲第幾個信號量
3 .cmd:爲以下取值:

在這裏插入圖片描述
在這裏插入圖片描述
4 .union semun arg : 爲以下取值:

union semun
{
     int val;
     strut semid* buf;
     unsigned  short* array;
};

在這裏插入圖片描述

三 . semop函數:

int semop(int semid, struct sembuf sops, size_t nsops)

1. semid:爲信號量集標識符
2. sembuf *sops(可以爲結構體數組首地址):爲以下取值:

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

在這裏插入圖片描述
3. nsops:sembuf *sops個數

未互斥計數:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main()
{
	int pid;
	int count = 0;
	pid = fork();
	if(pid > 0)
	{
		while(count < 1000) 
		{
			count++;
			printf("父進程:%d\n",count);
		}
		wait(NULL); //等待子進程退出
	}
	else if(pid == 0) 
	{
		while(count < 1000) 
		{
			count++;
			printf("子進程:%d\n",count);
		}
	}
	else if(pid < 0)
	{
		printf("fork error\n");
		exit(1);
	}
	return 0;
}

父進程創建出子進程,倆進程各計數到1000,並打印出來,由於未使用信號量實現倆進程互斥,所以父子進程會交替打印。
在這裏插入圖片描述

信號量互斥計數:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/stat.h>
struct sembuf add_sop,cut_sop;
union semun
{
	int val;
	struct semid_ds *buf;
	unsigned short *array;
};
void add_init()
{
       add_sop.sem_num = 0;
       add_sop.sem_op = 1; //p操作
       add_sop.sem_flg = 0;
}
void cut_init()
{
	cut_sop.sem_num = 0;
	cut_sop.sem_op = -1; //v操作
	cut_sop.sem_flg = 0;
}
int main()
{
	int count = 0;;
	int semid;
	union semun arg;
	int pid;
	arg.val = 1;
	add_init();
	cut_init();
	semid = semget(IPC_PRIVATE,1,IPC_CREAT | S_IRUSR | S_IWUSR); //信號量個數爲1
	semctl(semid,0,SETVAL,arg); //設置信號量0的值爲1
    pid = fork();
	if(pid > 0) // 父進程
	{

		semop(semid,&cut_sop,1); // 信號量p操作
        while(count < 1000)
	    {
			count++;
			printf("父進程:%d\n",count);
		}
		semop(semid,&add_sop,1); // 信號量v操作
		wait(NULL);  //等待子進程退出
	}
	else if(pid == 0) //子進程
	{
		semop(semid,&cut_sop,1); // 信號量p操作
        while(count < 1000)
	    {
			count++;
			printf("子進程:%d\n",count);
		}
		semop(semid,&add_sop,1); // 信號量v操作
	}
	else if(pid < 0)
	{
		printf("fork error\n");
		exit(1);
	}
	return 0;
}

加入信號量後,倆進程能夠實現互斥。一個進程在計數打印,另一個進程p操作就會使信號量小於0,進而阻塞,必須要等待上一個進程計數打印完成後,進行v操作釋放信號量,纔會解除阻塞。
在這裏插入圖片描述

ipcs -s : 查看已有信號量集

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章