一 信號量的基本概念
信號量:它是一個特殊變量,只允許對它進行等待和發送信號這兩種操作。
假設有一個信號量變量sv
P(sv):用于等待,如果sv的值大于零,就給它減去1,如果它的值等于零,就掛起該進程的執行。
V(sv):用于發送信號,如果有其他進程因等待sv而被掛起,就讓它恢復運行,如果沒有進程因等待sv而被掛起,就給它加1
二 信號量的相關函數
#include <sys/sem.h>
//semctl函數的作用是用來直接控制信號量信息 int semctl( int sem_id, //由semget返回的信號量標識符
int sem_num, //是信號量編號,當需要用到成組的信號量時,就要用到這個參數,它一般取值為0,表示這是第一個也是唯一的信號量
int command, //是將要采取的動作
... //它將會是一個union semun結構
);
//semget函數的作用是創建一個新信號量或取得一個已有信號量的鍵。 int semget(key_t key, //key是整數值,不相關的進程可以通過它訪問同一個信號量
int num_sems, //指定需要的信號量數目,幾乎總是取值為1
int sem_flags //是一組標志,與open函數的標志非常相似
); //在成功時返回一個正數(非零)值,它就是其他信號量函數將用到的信號量標識符,如果失敗,則返回-1
//semop函數用于改變信號量的值 int semop( int sem_id, //由semget返回的信號量標識符
struct sembuf *sem_ops, //指向一個 sembuf 結構數組的指針
size_t num_sem_ops //信號操作結構的數量,恒大于或等于1
);
semun包含于semun.h頭文件中
union semun{
int
val;
//SETVAL所設置的信號量集中的一個信號量的值
struct
semid_ds *
buf;
//IPC_STAT,IPC_SET存儲的數據
unsigned
short
*
array;
//GETALL, SETALL返回值的數組
}
semop函數中的sembuf結構體
struct
sembuf{
short
sem_num;
//信號量編號,除非需要使用一組信號量,否則它的取值一般為0
short
sem_op;
//是信號量在一次操作中需要改變的數值,通常只會用到兩個值,一個是-1,也就是P操作,它等待信號量變為己用;一個是+1,也就是V操作,它發送信號表示信號量現在已可用
short
sem_flg;
//通常設置為SEM_UNDO,它將使得操作系統跟蹤當前進程對這個信號量的修改情況
}
semctl中第三個參數command取值如下:
三 例子
#include <unistd.h>
#include
<stdlib.h>
#include
<stdio.h>
#include
<sys/sem.h>
#include
"
semun.h
"
static
int
set_semvalue(
void
);
static
void
del_semvalue(
void
);
static
int
semaphore_p(
void
);
static
int
semaphore_v(
void
);
static
int
sem_id;
int
main(
int
argc,
char
*
argv[]){
int
i;
int
pause_time;
char
op_char=
'
0
'
; srand((unsigned
int
)getpid()); sem_id
=semget((key_t)
1234
,
1
,
0666
|
IPC_CREAT);
if
(argc>
1
){
if
(!
set_semvalue()){ fprintf(stderr,
"
Failed to initialize semaphore\n
"
); exit(EXIT_FAILURE); } op_char
=
'
X
'
; sleep(
2
); }
//
進入和離開臨界區域10次,在每次循環的開始,首先調用semaphore函數,它在程序進入臨界區域時設置信號量以等待進入
for
(i=
0
;i<
10
;i++
){
if
(!
semaphore_p()){ exit(EXIT_FAILURE); } printf(
"
%c
"
,op_char); fflush(stdout); pause_time
=rand()%
3
; sleep(pause_time); printf(
"
%c
"
,op_char); fflush(stdout);
//
臨界區域之后,調用semaphore_v來將信號量設置為可用,然后等待一段隨機時間,再進入下一次循環。在整個循環語句執行完畢后,調用del_semvalue函數來清理代碼
if
(!
semaphore_v()){ exit(EXIT_FAILURE); } pause_time
=rand()%
2
; sleep(pause_time); } printf(
"
\n%d - finished\n
"
,getpid());
if
(argc>
1
){ sleep(
5
); del_semvalue(); } exit(EXIT_SUCCESS); }
//
函數set_semvalue通過將semct1調用的command參數設置為SETVAL來初始化信號量
static
int
set_semvalue(
void
){ union semun sem_union; sem_union.val
=
1
;
if
(semctl(sem_id,
0
,SETVAL,sem_union)==-
1
){
return
0
; }
return
1
; }
static
void
del_semvalue(
void
){ union semun sem_union;
if
(semctl(sem_id,
0
,IPC_RMID,sem_union)==-
1
){ fprintf(stderr,
"
Failed to delete semaphore
"
); } }
//
semaphore_p對信號量做減1操作(等待)
static
int
semaphore_p(
void
){
struct
sembuf sem_b; sem_b.sem_num
=
0
; sem_b.sem_op
=-
1
; sem_b.sem_flg
=
SEM_UNDO;
if
(semop(sem_id,&sem_b,
1
)==-
1
){ fprintf(stderr,
"
semaphore_p failed\n
"
);
return
0
; }
return
1
; }
//
semaphore_v將sembuf結構中的sem_op設置為1,釋放操作
static
int
semaphore_v(
void
){
struct
sembuf sem_b; sem_b.sem_num
=
0
; sem_b.sem_op
=
1
; sem_b.sem_flg
=
SEM_UNDO;
if
(semop(sem_id,&sem_b,
1
)==-
1
){ fprintf(stderr,
"
semaphore_v failed\n
"
);
return
0
; }
return
1
; }
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
