linux 訊號量、共用記憶體、和訊息佇列

來源:互聯網
上載者:User

Linux的訊號量機制

#include<sys/sem.h>

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

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

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

標頭檔sys/sem.h通常依賴於另外兩個有檔案sys/types.h和sys/ipc.h。一般情況下,他們會被sys/sem.h自動包含,因此不需要為它們明確添加相應的#include語句。

參數key的作用很像一個檔案名稱,它代表程式可能要使用的某個資源,如果多個程式使用相同的key值,它將負責協調工作。

1.semget函數

semget函數的作用是建立一個新訊號量或取得一個已有訊號量的鍵:

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

第一個參數是整數值,不相關的進程可以通過它訪問同一個訊號量。只有semget函數才直接使用訊號量鍵,所有其他的訊號量函數都是使用有semget函數返回的訊號量標識符。

num_sems指定需要的訊號量的數目,它幾乎總是取值為1。

sem_flags參數是一組標誌,它與open函數的標誌非常相識。

2.semop函數

semop函數用於改變訊號量的值,它的定義如下所示:

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

第一個參數sem_id是由semget返回的訊號量標識符。第二個參數sem_ops是指向一個結構數組的指標,每個數組元素至少包含一下幾個成員:

struct sembuf

{

short sem_num;

short sem_op;

short sem_flg;

}

第一個成員sem_num是訊號量編寫,除非你需要使用一組訊號量,否則它的取值一般是0。

sem_op成員的值是訊號量在一次操作中需要改變的數值。通常只會用到兩個值,一個是-1,也就是P操作,它等待訊號量變為可用。另外一個是V操作,它是+1,它發送訊號表示訊號量現在可用。

最後一個成員sem_flg通常被設定為SEM_UNDO。它將是的作業系統跟蹤當前進程對這個訊號量的修改情況。如果這個進程在沒有釋放該訊號量的情況下終止,作業系統將自動釋放該進程持有的訊號量。

3.semctl函數

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

第一個參數sem_id是由semget返回的訊號量標識符。sem_num參數是訊號量編寫,當需要用到成組的訊號量時,就要用到這個參數,它一般取值為0,表示這是第一個唯一的一個訊號量。command參數是將要採取的動作。如果還有第四個參數,它將會是一個union semun結構,它至少包含一下幾個成員:

union semun

{

int val;

struct semid_ds *buf;

unsigned short *array;

}

semctl函數中的command參數可以設定許多不同的值,但只有下面介紹的兩個值最常用。

SETVAL:用來把訊號量初始化為一個已知的值。這個用過union semun中的val成員設定。

IPC_RMID:用於刪除一個已經無需繼續使用的訊號量標識符。

/* After the #includes, the function prototypes and the global variable, we come to the main function. There the semaphore is created with a call to semget, which returns the semaphore ID. If the program is the first to be called (i.e. it's called with a parameter and argc > 1), a call is made to set_semvalue to initialize the semaphore and op_char is set to X. */#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 = 'O';    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);    }/* Then we have a loop which enters and leaves the critical section ten times. There, we first make a call to semaphore_p which sets the semaphore to wait, as this program is about to enter the critical section. */    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);/* After the critical section, we call semaphore_v, setting the semaphore available, before going through the for loop again after a random wait. After the loop, the call to del_semvalue is made to clean up the code. */        if (!semaphore_v()) exit(EXIT_FAILURE);                pause_time = rand() % 2;        sleep(pause_time);    }        printf("\n%d - finished\n", getpid());    if (argc > 1) {            sleep(10);        del_semvalue();    }            exit(EXIT_SUCCESS);}/* The function set_semvalue initializes the semaphore using the SETVAL command in a semctl call. We need to do this before we can use the semaphore. */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);}/* The del_semvalue function has almost the same form, except the call to semctl uses the command IPC_RMID to remove the semaphore's ID. */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\n");}/* semaphore_p changes the semaphore by -1 (waiting). */static int semaphore_p(void){    struct sembuf sem_b;        sem_b.sem_num = 0;    sem_b.sem_op = -1; /* P() */    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 is similar except for setting the sem_op part of the sembuf structure to 1, so that the semaphore becomes available. */static int semaphore_v(void){    struct sembuf sem_b;        sem_b.sem_num = 0;    sem_b.sem_op = 1; /* V() */    sem_b.sem_flg = SEM_UNDO;    if (semop(sem_id, &sem_b, 1) == -1) {        fprintf(stderr, "semaphore_v failed\n");        return(0);    }    return(1);}
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.