天天看點

linux system v信号量,Linux中的System V信号量

在程序同步,并發運作時,保證按序地通路共享資源是十分重要的。是以引入了臨界區的概念,一次隻能有一個線程進入臨界區完成他的指令。而信号量(semaphore)的作用,類似于一個交通信号燈,它負責程序協作,是以信号量又稱為信号燈。

在Linux系統中,它提供兩種信号量:

核心信号量,由核心控制路徑使用

使用者态程序使用的信号量,這種信号量有兩種接口,POSIX信号量和SYSTEM V信号量。

信号量的本質是一個計數器。一個較為常見的用法,是為每個資源都會配置設定一個信号量。記信号量為S,除了初始化之外,有兩個标準原子操作:wait()和signal()。

System V信号量接口

semget

建立一個新信号量或取得一個已有信号量

int semget(key_t key, int num_sems, int sem_flags);

key是一個整數值(唯一非零),可以了解成是信号量的辨別符。

num_sems指定了需要的信号量數目,通常為1。

sem_flags是一組标志,當建立一個新的信号量時,設定權限與值IPC_CREAT做按位或操作。設定了IPC_CREAT标志後,即使給出的鍵是一個已有信号量的鍵,也不會産生錯誤。而IPC_CREAT | IPC_EXCL則可以建立一個新的,唯一的信号量,如果信号量已存在,傳回一個錯誤。

函數成功傳回一個相應信号辨別符(非零),失敗傳回-1。

semctl

直接控制信号量資訊

int semctl(int sem_id, int sem_num, int command, ...);

第二個參數是操作信号在信号集中的編号,第一個信号的編号是0。

第三個參數command通常是下面兩個值中的其中一個:

SETVAL:用來把信号量初始化為一個已知的值。

IPC_RMID:用于删除一個已經無需繼續使用的信号量辨別符。

如果有第四個參數,它通常是一個union semum結構,定義如下:

union semun

{

int val;

struct semid_ds *buf;

unsigned short *arry;

};

semop

改變信号量的值

int semop(int sem_id, struct sembuf *sem_opa, size_t num_sem_ops);

sem_id是由semget傳回的信号量辨別符,sembuf結構的定義如下:

struct sembuf{

short sem_num;//除非使用一組信号量,否則為0

short sem_op;//信号量在一次操作中需要改變的資料,-1即P(等待)操作,+1即V(發送信号)操作。

short sem_flg;//通常為SEM_UNDO,使作業系統跟蹤信号,并在程序沒有釋放該信号量而終止時,作業系統釋放信号量

};

程序同步執行個體

無信号量執行個體

#include

#include

#include

int main()

{

pid_t pid;

pid = fork();

srand(pid);

if(pid > 0) // parent process

{

char a = 'A'; // char to print

for(int i = 0; i < 10; ++i)

{

printf("%c", a);

fflush(stdout); // flush stdout buffer

sleep(1);

printf("%c", a);

fflush(stdout);

sleep(1);

}

}

else // child process

{

char b = 'B';

for(int i = 0; i < 10; ++i)

{

printf("%c", b);

fflush(stdout);

sleep(1);

printf("%c", b);

fflush(stdout);

sleep(1);

}

}

printf("n%d - finishedn", getpid());

sleep(3);

return 0;

}

運作結果

linux system v信号量,Linux中的System V信号量

有信号量執行個體

#include

#include

#include

#include

#include

#include

#include

#define SEMKEY 0x00002222 // set a key for semaphore

union semun // union for semaphore

{

int val;

struct semid_ds *buf;

unsigned short *array;

};

struct sembuf p = { 0, -1, SEM_UNDO};

struct sembuf v = { 0, +1, SEM_UNDO};

int main()

{

int sem_id = semget(SEMKEY, 1, 0666 | IPC_CREAT); // get semaphore

union semun sem_union;

sem_union.val = 1;

if(semctl(sem_id, 0, SETVAL, sem_union) < 0)

{

perror("semctl error");

return -1;

}

int pid;

pid = fork();

srand(pid);

if(pid > 0) // parent process

{

char a = 'A'; // char to print

for(int i = 0; i < 10; ++i)

{

if(semop(sem_id, &p, 1) < 0) // P operation

{

perror("semop p error");

return -1;

}

printf("%c", a);

fflush(stdout); // flush stdout buffer

sleep(1);

printf("%c", a);

fflush(stdout);

if(semop(sem_id, &v, 1) < 0) // V operation

{

perror("semop v error");

return -1;

}

sleep(1);

}

}

else // child process

{

char b = 'B'; // char to print

for(int i = 0; i < 10; ++i)

{

if(semop(sem_id, &p, 1) < 0) // P operation

{

perror("semop p error");

return -1;

}

printf("%c", b);

fflush(stdout); // flush stdout buffer

sleep(1);

printf("%c", b);

fflush(stdout);

if(semop(sem_id, &v, 1) < 0) // V operation

{

perror("semop v error");

return -1;

}

sleep(1);

}

}

printf("n%d - finishedn", getpid());

sleep(3);

if (pid > 0)

{

system("ipcrm -S 0x00002222");

}

return 0;

}

運作結果

linux system v信号量,Linux中的System V信号量

因為設定信号量的關系,一個線程在臨界區内一定會執行兩次print()操作,是以A或B一定成對出現。

程式員燈塔

轉載請注明原文連結:Linux中的System V信号量