国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Linux:淺談信號量

2019-11-08 03:28:03
字體:
來源:轉載
供稿:網友

1.信號量的概念。 信號量的本質是一種數據操作鎖,它本?身不具有數據交換的功能,而是通過控制其他的通信資源(文件,外部設備)來實現進程間通信,它本?身只是一種外部資源的標識。信號量在此過程中負責數據操作的互斥、同步等功能。 當請求一個使用信號量來表示的資源時,進程需要先讀取信號量的值來判斷資源是否可用。大于0,資源可以請求,等于0,無資源可用,進程會進?入睡眠狀態直至資源可用。 當進程不再使用一個信號量控制的共享資源時,信號量的值+1,對信號量的值進行的增減 操作均為原子操作,這是由于信號量主要的作用是維護資源的互斥或多進程的同步訪問。 而在信號量的創建及初始化上,不能保證操作均為原子性。 2.信號量是如何工作的 由于信號量只能進?行兩種操作等待和發送信號,即P(sv)和V(sv),他們的?行為是這樣的: P(sv):如果sv的值?大于零,就給它減1;如果它的值為零,就掛起該進程的執?行 V(sv):如果有其他進程因等待sv?而被掛起,就讓它恢復運?行,如果沒有進程因等待sv?而掛 起,就給它加1. 3.相關函數  函數原型:int semget(key_t key,int nsems,int semflg);  參數解釋: key:所創建或打開信號量集的鍵值。需要是唯一的非零整數。   nsems:創建的信號量集中的信號量的個數,該參數只在創建信號量集時有效。幾乎總是取值為1.   flag:調用函數的操作類型,也可用于設置信號量集的訪問權限,用或來表示。

  功能描述   獲取與某個鍵關聯的信號量集標識。信號量集被建立的情況有兩種:   1.如果鍵的值是ipC_PRIVATE。   2.或者鍵的值不是IPC_PRIVATE,并且鍵所對應的信號量集不存在,同時標志中指定IPC_CREAT。   當調用semget創建一個信號量時,他的相應的semid_ds結構被初始化。ipc_perm中各個量被設置為相應   值:   sem_nsems被設置為nsems所示的值;   sem_otime被設置為0;   sem_ctime被設置為當前時間。 函數原型:int semop( int semid, struct sembuf semoparray[], size_t nops ); 參數解釋: 參數semid是一個通過semget函數返回的一個信號量標識符 參數nops標明了參數semoparray所指向數組中的元素個數 參數semoparray是一個struct sembuf結構類型的數組指針, 結構sembuf來說明所要執行的操作,其成員如下: 這里寫圖片描述 其中sem_flg說明函數semop的行為。通常被設置為SEM_UNDO。它將使得操作系統跟著當前進程對這個信號量的修改情況,如果這個進程在沒有釋放該信號量的情況下終止,操作系統將自動釋放該進程持有的信號量。

函數原型:int semctl(int semid,int semnum,int cmd,…); 參數解釋: sem_id是由semget返回的信號量標識符。 sem_num與前面一個函數相同。 cmd:表示將要采取的動作。 如果有第四個參數,一般為聯合體semun,成員如下: 這里寫圖片描述

信號量使用的簡單示例: 我們創建一個進程,代碼如下:

#include"head.h"#include<unistd.h>#include<sys/wait.h>int main(){ int sem_id = my_semget(1); initial(sem_id, 0); pid_t id = fork();//創建一個子進程 if (0 == id){ while(1){ //上鎖 if ( sem_p(sem_id, 0) == -1){ perror("children p error"); exit(0); } usleep(10200); printf("A"); fflush(stdout); usleep(23043); printf("A"); fflush(stdout); if ( sem_v(sem_id,0) == -1){ perror("children v error"); exit(0); } } } else{ while(1){ //上鎖 if ( sem_p(sem_id, 0) == -1){ perror("father p error"); exit(0); } usleep(10200); usleep(16200); printf("B"); fflush(stdout); usleep(33043); printf("B"); fflush(stdout); if ( sem_v(sem_id,0) == -1){ perror("father v error"); exit(0); } } int stat = 0; wait(&stat); }}

在沒有信號量之前,因為有睡眠延時,系統會隨機打印A和B,如: 這里寫圖片描述 添加信號量之后,因為A進程在信號量上鎖后,sv值變為0,則B進程會掛起,直到A進程解鎖,則系統會有規律的打印A和B。 這里寫圖片描述

head.h:#ifndef _HEAD_#define _HEAD_#include<stdio.h>#include<stdlib.h>#include<sys/sem.h>#include<sys/types.h>#include<sys/ipc.h>#define _PATH "."#define _NUM 0x98union semun { int val; // 使?用的值 struct semid_ds *buf; // IPC_STAT、IPC_SET 使?用緩存區 unsigned short *array; // GETALL,、SETALL 使?用的數組 struct seminfo *__buf; // IPC_INFO(linux特有) 使?用緩存區};int my_semget(int sem_num);int getsem();int initial(int sem_id, int which);int sem_p(int sem_id, int which);int sem_v(int sem_id, int which);int destroy(int sem_id);#endifhead.c:#include "head.h"#include<string.h>int static semgeting(int sem_num, int flag){ key_t key = ftok(_PATH, _NUM); return semget(key,sem_num, flag);}int static op_chang(int sem_id, int which, int op){ sembuf sem_t; memset(&sem_t, 0, sizeof(sembuf)); sem_t.sem_num = which; sem_t.sem_op = op; sem_t.sem_flg = 0; return semop(sem_id, &sem_t,1);}int my_semget(int sem_num){ return semgeting(sem_num, IPC_CREAT|IPC_EXCL|0666);}int getsem(){ return semgeting(0, 0);}int initial(int sem_id, int which){ semun sem_t; sem_t.val = 1; return semctl(sem_id, which, SETVAL, sem_t);}int sem_p(int sem_id, int which){ sembuf sem_t; return op_chang(sem_id, which,-1); }int sem_v(int sem_id, int which){ return op_chang(sem_id, which, 1); }int destroy(int sem_id){ return semctl(sem_id, 0, IPC_RMID, NULL);}
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 开化县| 河西区| 张掖市| 巫溪县| 长海县| 焉耆| 东辽县| 库尔勒市| 建始县| 玉树县| 深泽县| 应用必备| 嘉荫县| 基隆市| 钟祥市| 濮阳市| 靖安县| 基隆市| 长岭县| 班玛县| 垦利县| 沙田区| 始兴县| 桐梓县| 仪征市| 平乐县| 名山县| 麟游县| 定结县| 玉门市| 米林县| 洪雅县| 鄢陵县| 留坝县| 岱山县| 松阳县| 永善县| 锡林浩特市| 通化市| 诸城市| 淄博市|