Linux之信號量-比較全面-個人總結(jié)_第1頁
Linux之信號量-比較全面-個人總結(jié)_第2頁
Linux之信號量-比較全面-個人總結(jié)_第3頁
Linux之信號量-比較全面-個人總結(jié)_第4頁
Linux之信號量-比較全面-個人總結(jié)_第5頁
已閱讀5頁,還剩14頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)

文檔簡介

1、 信號量一什么是信號量信號量的使用主要是用來保護共享資源,使得資源在一個時刻只有一個進程線程所擁有。信號量的值為正的時候,說明它空閑。所測試的線程可以鎖定而使用它。假設(shè)為0,說明它被占用,測試的線程要進入睡眠隊列中,等待被喚醒。二信號量的分類在學(xué)習(xí)信號量之前,我們必須先知道Linux提供兩種信號量:(1) 內(nèi)核信號量,由內(nèi)核控制路徑使用(2) 用戶態(tài)進程使用的信號量,這種信號量又分為POSIX信號量和SYSTEM V信號量。POSIX信號量又分為有名信號量和無名信號量。有名信號量,其值保存在文件中, 所以它可以用于線程也可以用于進程間的同步。無名信號量,其值保存在內(nèi)存中。倘假設(shè)對信號量沒有以上

2、的全面認(rèn)識的話,你就會很快發(fā)現(xiàn)自己在信號量的森林里迷失了方向。三內(nèi)核信號量1內(nèi)核信號量的構(gòu)成內(nèi)核信號量類似于自旋鎖,因為當(dāng)鎖關(guān)閉著時,它不允許內(nèi)核控制路徑繼續(xù)進行。然而,當(dāng)內(nèi)核控制路徑試圖獲取內(nèi)核信號量鎖保護的忙資源時,相應(yīng)的進程就被掛起。只有在資源被釋放時,進程才再次變?yōu)榭蛇\行。只有可以睡眠的函數(shù)才能獲取內(nèi)核信號量;中斷處理程序和可延遲函數(shù)都不能使用內(nèi)核信號量。內(nèi)核信號量是struct semaphore類型的對象,它在<asm/semaphore.h>中定義:struct semaphore atomic_t count; int sleepers; wait_queue_he

3、ad_t wait;count:相當(dāng)于信號量的值,大于0,資源空閑;等于0,資源忙,但沒有進程等待這個保護的資源;小于0,資源不可用,并至少有一個進程等待資源。wait:存放等待隊列鏈表的地址,當(dāng)前等待資源的所有睡眠進程都會放在這個鏈表中。sleepers:存放一個標(biāo)志,表示是否有一些進程在信號量上睡眠。2內(nèi)核信號量中的等待隊列刪除,沒有聯(lián)系上面已經(jīng)提到了內(nèi)核信號量使用了等待隊列wait_queue來實現(xiàn)阻塞操作。當(dāng)某任務(wù)由于沒有某種條件沒有得到滿足時,它就被掛到等待隊列中睡眠。當(dāng)條件得到滿足時,該任務(wù)就被移出等待隊列,此時并不意味著該任務(wù)就被馬上執(zhí)行,因為它又被移進工作隊列中等待CPU資源,

4、在適當(dāng)?shù)臅r機被調(diào)度。內(nèi)核信號量是在內(nèi)部使用等待隊列的,也就是說該等待隊列對用戶是隱藏的,無須用戶干預(yù)。由用戶真正使用的等待隊列我們將在另外的篇章進行詳解。3內(nèi)核信號量的相關(guān)函數(shù)1初始化:void sema_init (struct semaphore *sem, int val);void init_MUTEX (struct semaphore *sem); /將sem的值置為1,表示資源空閑void init_MUTEX_LOCKED (struct semaphore *sem); /將sem的值置為0,表示資源忙2申請內(nèi)核信號量所保護的資源:void down(struct semap

5、hore * sem); / 可引起睡眠int down_interruptible(struct semaphore * sem); / down_interruptible能被信號打斷int down_trylock(struct semaphore * sem); / 非阻塞函數(shù),不會睡眠。無法鎖定資源則馬上返回3釋放內(nèi)核信號量所保護的資源:void up(struct semaphore * sem);4內(nèi)核信號量的使用例程在驅(qū)動程序中,當(dāng)多個線程同時訪問相同的資源時驅(qū)動中的全局變量時一種典型的共享資源,可能會引發(fā)“競態(tài)“,因此我們必須對共享資源進行并發(fā)控制。Linux內(nèi)核中解決并發(fā)控

6、制的最常用方法是自旋鎖與信號量絕大多數(shù)時候作為互斥鎖使用。ssize_t globalvar_write(struct file *filp, const char *buf, size_t len, loff_t *off)/獲得信號量if (down_interruptible(&sem)return - ERESTARTSYS;/將用戶空間的數(shù)據(jù)復(fù)制到內(nèi)核空間的global_varif (copy_from_user(&global_var, buf, sizeof(int)up(&sem);return - EFAULT;/釋放信號量up(&sem);r

7、eturn sizeof(int);四POSIX 信號量與SYSTEM V信號量的比較1. 對POSIX來說,信號量是個非負(fù)整數(shù)。常用于線程間同步。而SYSTEM V信號量則是一個或多個信號量的集合,它對應(yīng)的是一個信號量結(jié)構(gòu)體,這個結(jié)構(gòu)體是為SYSTEM V IPC服務(wù)的,信號量只不過是它的一部分。常用于進程間同步。2POSIX信號量的引用頭文件是“<semaphore.h>”,而SYSTEM V信號量的引用頭文件是“<sys/sem.h>”。3從使用的角度,System V信號量是復(fù)雜的,而Posix信號量是簡單。比方,POSIX信號量的創(chuàng)建和初始化或PV操作就很非常

8、方便。五POSIX信號量詳解1無名信號量無名信號量的創(chuàng)建就像聲明一般的變量一樣簡單,例如:sem_t sem_id。然后再初始化該無名信號量,之后就可以放心使用了。無名信號量常用于多線程間的同步,同時也用于相關(guān)進程間的同步。也就是說,無名信號量必須是多個進程線程的共享變量,無名信號量要保護的變量也必須是多個進程線程的共享變量,這兩個條件是缺一不可的。常見的無名信號量相關(guān)函數(shù):sem_destroyint sem_init(sem_t *sem, int pshared, unsigned int value);    1)pshared=0 用于同一多線程的同步;

9、    2)假設(shè)pshared>0 用于多個相關(guān)進程間的同步即由fork產(chǎn)生的int sem_getvalue(sem_t *sem, int *sval);    取回信號量sem的當(dāng)前值,把該值保存到sval中。    假設(shè)有1個或更多的線程或進程調(diào)用sem_wait阻塞在該信號量上,該函數(shù)返回兩種值:        1) 返回0        2) 返回阻塞在該信號量上的進程

10、或線程數(shù)目    linux采用返回的第一種策略。sem_wait(或sem_trywait)相當(dāng)于P操作,即申請資源。int sem_wait(sem_t *sem); / 這是一個阻塞的函數(shù)    測試所指定信號量的值,它的操作是原子的。    假設(shè)sem>0,那么它減1并立即返回。    假設(shè)sem=0,則睡眠直到sem>0,此時立即減1,然后返回。int sem_trywait(sem_t *sem); / 非阻塞的函數(shù)   

11、 其他的行為和sem_wait一樣,除了:    假設(shè)sem=0,不是睡眠,而是返回一個錯誤EAGAIN。sem_post相當(dāng)于V操作,釋放資源。int sem_post(sem_t *sem);    把指定的信號量sem的值加1;    呼醒正在等待該信號量的任意線程。注意:在這些函數(shù)中,只有sem_post是信號安全的函數(shù),它是可重入函數(shù)a無名信號量在多線程間的同步無名信號量的常見用法是將要保護的變量放在sem_wait和sem_post中間所形成的臨界區(qū)內(nèi),這樣該變量就會被保護起來,例如:#inc

12、lude <pthread.h>#include <semaphore.h>#include <sys/types.h>#include <stdio.h>#include <unistd.h>int number; / 被保護的全局變量sem_t sem_id;void* thread_one_fun(void *arg)sem_wait(&sem_id);printf("thread_one have the semaphoren");number+;printf("number = %dn&

13、quot;,number);sem_post(&sem_id);void* thread_two_fun(void *arg)sem_wait(&sem_id);printf("thread_two have the semaphore n");number-;printf("number = %dn",number);sem_post(&sem_id);int main(int argc,char *argv) number = 1;pthread_t id1, id2; sem_init(&sem_id, 0, 1);

14、pthread_create(&id1,NULL,thread_one_fun, NULL);pthread_create(&id2,NULL,thread_two_fun, NULL);pthread_join(id1,NULL);pthread_join(id2,NULL);printf("main,n");return 0;上面的例程,到底哪個線程先申請到信號量資源,這是隨機的。如果想要某個特定的順序的話,可以用2個信號量來實現(xiàn)。例如下面的例程是線程1先執(zhí)行完,然后線程2才繼續(xù)執(zhí)行,直至結(jié)束。int number; / 被保護的全局變量sem_t se

15、m_id1, sem_id2;void* thread_one_fun(void *arg)sem_wait(&sem_id1);printf("thread_one have the semaphoren");number+;printf("number = %dn",number);sem_post(&sem_id2);void* thread_two_fun(void *arg)sem_wait(&sem_id2);printf("thread_two have the semaphore n");num

16、ber-;printf("number = %dn",number);sem_post(&sem_id1);int main(int argc,char *argv) number = 1;pthread_t id1, id2;sem_init(&sem_id1, 0, 1); / 空閑的sem_init(&sem_id2, 0, 0); / 忙的pthread_create(&id1,NULL,thread_one_fun, NULL);pthread_create(&id2,NULL,thread_two_fun, NULL);p

17、thread_join(id1,NULL);pthread_join(id2,NULL);printf("main,n");return 0;b無名信號量在相關(guān)進程間的同步說是相關(guān)進程,是因為本程序中共有2個進程,其中一個是另外一個的子進程由fork產(chǎn)生的。 本來對于fork來說,子進程只繼承了父進程的代碼副本,mutex理應(yīng)在父子進程中是相互獨立的兩個變量,但由于在初始化mutex的時候,由pshared = 1指定了mutex處于共享內(nèi)存區(qū)域,所以此時mutex變成了父子進程共享的一個變量。此時,mutex就可以用來同步相關(guān)進程了。#include <semaph

18、ore.h>#include <stdio.h>#include <errno.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/mman.h>int main(int argc, char *argv)int fd, i,count=0,nloop=10,zero=0,*ptr; sem_t mutex; /ope

19、n a file and map it into memory fd = open("log.txt",O_RDWR|O_CREAT,S_IRWXU); write(fd,&zero,sizeof(int); ptr = mmap( NULL,sizeof(int),PROT_READ |PROT_WRITE,MAP_SHARED,fd,0 ); close(fd); /* create, initialize semaphore */ if( sem_init(&mutex,1,1) < 0) / perror("semaphore ini

20、tilization"); exit(0); if (fork() = 0) /* child process*/for (i = 0; i < nloop; i+) sem_wait(&mutex); printf("child: %dn", (*ptr)+); sem_post(&mutex); exit(0); /* back to parent process */for (i = 0; i < nloop; i+) sem_wait(&mutex); printf("parent: %dn", (*

21、ptr)+); sem_post(&mutex); exit(0);2有名信號量有名信號量的特點是把信號量的值保存在文件中。這決定了它的用途非常廣:既可以用于線程,也可以用于相關(guān)進程間,甚至是不相關(guān)進程。a有名信號量能在進程間共享的原因由于有名信號量的值是保存在文件中的,所以對于相關(guān)進程來說,子進程是繼承了父進程的文件描述符,那么子進程所繼承的文件描述符所指向的文件是和父進程一樣的,當(dāng)然文件里面保存的有名信號量值就共享了。b有名信號量相關(guān)函數(shù)說明有名信號量在使用的時候,和無名信號量共享sem_wait和sem_post函數(shù)。區(qū)別是有名信號量使用sem_open代替sem_init,另外

22、在結(jié)束的時候要像關(guān)閉文件一樣去關(guān)閉這個有名信號量。(1)打開一個已存在的有名信號量,或創(chuàng)建并初始化一個有名信號量。一個單一的調(diào)用就完成了信號量的創(chuàng)建、初始化和權(quán)限的設(shè)置。sem_t *sem_open(const char *name,  int oflag, mode_t mode , int value);name是文件的路徑名;Oflag 有O_CREAT或O_CREAT|EXCL兩個取值;mode_t控制新的信號量的訪問權(quán)限;Value指定信號量的初始化值。注意:這里的name不能寫成/tmp/aaa.sem這樣的格式,因為在linux下,sem都是創(chuàng)建在/dev/

23、shm目錄下。你可以將name寫成“/mysem”或“mysem”,創(chuàng)建出來的文件都是“”,千萬不要寫路徑。也千萬不要寫“/tmp/mysem”之類的。當(dāng)oflag = O_CREAT時,假設(shè)name指定的信號量不存在時,則會創(chuàng)建一個,而且后面的mode和value參數(shù)必須有效。假設(shè)name指定的信號量已存在,則直接打開該信號量,同時忽略mode和value參數(shù)。當(dāng)oflag = O_CREAT|O_EXCL時,假設(shè)name指定的信號量已存在,該函數(shù)會直接返回error。(2) 一旦你使用了一信號量,銷毀它們就變得很重要。在做這個之前,要確定所有對這個有名信號量的引用都已經(jīng)通過sem_clos

24、e函數(shù)關(guān)閉了,然后只需在退出或是退出處理函數(shù)中調(diào)用sem_unlink()去刪除系統(tǒng)中的信號量,注意如果有任何的處理器或是線程引用這個信號量,sem_unlink()函數(shù)不會起到任何的作用。也就是說,必須是最后一個使用該信號量的進程來執(zhí)行sem_unlick才有效。因為每個信號燈有一個引用計數(shù)器記錄當(dāng)前的打開次數(shù),sem_unlink必須等待這個數(shù)為0時才能把name所指的信號燈從文件系統(tǒng)中刪除。也就是要等待最后一個sem_close發(fā)生。c有名信號量在無相關(guān)進程間的同步前面已經(jīng)說過,有名信號量是位于共享內(nèi)存區(qū)的,那么它要保護的資源也必須是位于共享內(nèi)存區(qū),只有這樣才能被無相關(guān)的進程所共享。在下

25、面這個例子中,服務(wù)進程和客戶進程都使用shmget和shmat來獲取得一塊共享內(nèi)存資源。然后利用有名信號量來對這塊共享內(nèi)存資源進行互斥保護。<u>File1: server.c </u>#include <sys/types.h>#include <sys/ipc.h>#include <sys/shm.h>#include <stdio.h>#include <semaphore.h>#include <sys/types.h>#include <sys/stat.h>#include

26、 <fcntl.h>#define SHMSZ 27char SEM_NAME= "vik"int main() char ch; int shmid; key_t key; char *shm,*s; sem_t *mutex; /name the shared memory segment key = 1000; /create & initialize semaphore mutex = sem_open(SEM_NAME,O_CREAT,0644,1); if(mutex = SEM_FAILED) perror("unable to

27、create semaphore"); sem_unlink(SEM_NAME); exit(-1); /create the shared memory segment with this key shmid = shmget(key,SHMSZ,IPC_CREAT|0666); if(shmid<0) perror("failure in shmget"); exit(-1); /attach this segment to virtual memory shm = shmat(shmid,NULL,0); /start writing into mem

28、ory s = shm; for(ch='A'ch<='Z'ch+) sem_wait(mutex); *s+ = ch; sem_post(mutex); /the below loop could be replaced by binary semaphore while(*shm != '*') sleep(1); sem_close(mutex); sem_unlink(SEM_NAME); shmctl(shmid, IPC_RMID, 0); exit(0);<u></u>#include <sys

29、/types.h>#include <sys/ipc.h>#include <sys/shm.h>#include <stdio.h>#include <semaphore.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#define SHMSZ 27char SEM_NAME= "vik"int main() char ch; int shmid; key_t key; char *shm,*s; sem

30、_t *mutex; /name the shared memory segment key = 1000; /create & initialize existing semaphore mutex = sem_open(SEM_NAME,0,0644,0); if(mutex = SEM_FAILED) perror("reader:unable to execute semaphore"); sem_close(mutex); exit(-1); /create the shared memory segment with this key shmid = s

31、hmget(key,SHMSZ,0666); if(shmid<0) perror("reader:failure in shmget"); exit(-1); /attach this segment to virtual memory shm = shmat(shmid,NULL,0); /start reading s = shm; for(s=shm;*s!=NULL;s+) sem_wait(mutex); putchar(*s); sem_post(mutex); /once done signal exiting of reader:This can b

32、e replaced by another semaphore *shm = '*' sem_close(mutex); shmctl(shmid, IPC_RMID, 0); exit(0);六SYSTEM V信號量這是信號量值的集合,而不是單個信號量。相關(guān)的信號量操作函數(shù)由<sys/ipc.h>引用。1信號量結(jié)構(gòu)體內(nèi)核為每個信號量集維護一個信號量結(jié)構(gòu)體,可在<sys/sem.h>找到該定義:struct semid_ds struct ipc_perm sem_perm; /* 信號量集的操作許可權(quán)限 */struct sem *sem_base;

33、/* 某個信號量sem結(jié)構(gòu)數(shù)組的指針,當(dāng)前信號量集中的每個信號量對應(yīng)其中一個數(shù)組元素 */ ushort sem_nsems; /* sem_base 數(shù)組的個數(shù) */ time_t sem_otime; /* 最后一次成功修改信號量數(shù)組的時間 */ time_t sem_ctime; /* 成功創(chuàng)建時間 */;struct sem     ushort semval;        /* 信號量的當(dāng)前值 */    short  sempid; 

34、0;      /* 最后一次返回該信號量的進程ID號 */    ushort semncnt;        /* 等待semval大于當(dāng)前值的進程個數(shù) */    ushort semzcnt;        /* 等待semval變成0的進程個數(shù) */;2常見的SYSTEM V信號量函數(shù)a關(guān)鍵字和描述符SYSTEM V信號量是SYSTEM V IPC即SYSTEM V進

35、程間通信的組成部分,其他的有SYSTEM V消息隊列,SYSTEM V共享內(nèi)存。而關(guān)鍵字和IPC描述符無疑是它們的共同點,也使用它們,就不得不先對它們進行熟悉。這里只對SYSTEM V信號量進行討論。IPC描述符相當(dāng)于引用ID號,要想使用SYSTEM V信號量或MSG、SHM,就必須用IPC描述符來調(diào)用信號量。而IPC描述符是內(nèi)核動態(tài)提供的通過semget來獲取,用戶無法讓服務(wù)器和客戶事先認(rèn)可共同使用哪個描述符,所以有時候就需要到關(guān)鍵字KEY來定位描述符。某個KEY只會固定對應(yīng)一個描述符這項轉(zhuǎn)換工作由內(nèi)核完成,這樣假設(shè)服務(wù)器和客戶事先認(rèn)可共同使用某個KEY,那么大家就都能定位到同一個描述符,也

36、就能定位到同一個信號量,這樣就到達(dá)了SYSTEM V信號量在進程間共享的目的。b創(chuàng)建和打開信號量int semget(key_t key, int nsems, int oflag)(1) nsems>0 : 創(chuàng)建一個信的信號量集,指定集合中信號量的數(shù)量,一旦創(chuàng)建就不能更改。(2) nsems=0 : 訪問一個已存在的集合(3) 返回的是一個稱為信號量標(biāo)識符的整數(shù),semop和semctl函數(shù)將使用它。 (4) 創(chuàng)建成功后信號量結(jié)構(gòu)被設(shè)置: .sem_perm 的uid和gid成員被設(shè)置成的調(diào)用進程的有效用戶ID和有效組ID .sem_otime 被置為0,sem_ctime被設(shè)置為當(dāng)前

37、時間 .sem_nsems 被置為nsems參數(shù)的值 該集合中的每個信號量不初始化,這些結(jié)構(gòu)是在semctl,用參數(shù)SET_VAL,SETALL初始化的。semget函數(shù)執(zhí)行成功后,就產(chǎn)生了一個由內(nèi)核維持的類型為semid_ds結(jié)構(gòu)體的信號量集,返回semid就是指向該信號量集的引索。c關(guān)鍵字的獲取有多種方法使客戶機和服務(wù)器在同一IPC結(jié)構(gòu)上會合:(1) 服務(wù)器可以指定關(guān)鍵字IPC_PRIVATE創(chuàng)建一個新IPC結(jié)構(gòu),將返回的標(biāo)識符存放在某處例如一個文件以便客戶機取用。關(guān)鍵字 IPC_PRIVATE保證服務(wù)器創(chuàng)建一個新IPC結(jié)構(gòu)。這種技術(shù)的缺點是:服務(wù)器要將整型標(biāo)識符寫到文件中,然后客戶機在此

38、后又要讀文件取得此標(biāo)識符。IPC_PRIVATE關(guān)鍵字也可用于父、子關(guān)系進程。父進程指定 IPC_PRIVATE創(chuàng)建一個新IPC結(jié)構(gòu),所返回的標(biāo)識符在fork后可由子進程使用。子進程可將此標(biāo)識符作為exec函數(shù)的一個參數(shù)傳給一個新程序。(2) 在一個公用頭文件中定義一個客戶機和服務(wù)器都認(rèn)可的關(guān)鍵字。然后服務(wù)器指定此關(guān)鍵字創(chuàng)建一個新的IPC結(jié)構(gòu)。這種方法的問題是該關(guān)鍵字可能已與一個 IPC結(jié)構(gòu)相結(jié)合,在此情況下,get函數(shù)msgget、semget或shmget出錯返回。服務(wù)器必須處理這一錯誤,刪除已存在的IPC結(jié)構(gòu),然后試著再創(chuàng)建它。當(dāng)然,這個關(guān)鍵字不能被別的程序所占用。(3) 客戶機和服務(wù)器

39、認(rèn)同一個路徑名和課題I D課題I D是0 2 5 5之間的字符值 ,然后調(diào)用函數(shù)ftok將這兩個值變換為一個關(guān)鍵字。這樣就防止了使用一個已被占用的關(guān)鍵字的問題。使用ftok并非高枕無憂。有這樣一種例外:服務(wù)器使用ftok獲取得一個關(guān)鍵字后,該文件就被刪除了,然后重建。此時客戶端以此重建后的文件來ftok所獲取的關(guān)鍵字就和服務(wù)器的關(guān)鍵字不一樣了。所以一般商用的軟件都不怎么用ftok。一般來說,客戶機和服務(wù)器至少共享一個頭文件,所以一個比較簡單的方法是防止使用ftok,而只是在該頭文件中存放一個大家都知道的關(guān)鍵字。d設(shè)置信號量的值PV操作int semop(int semid, struct se

40、mbuf *opsptr, size_t nops);(1) semid: 是semget返回的semid(2)opsptr: 指向信號量操作結(jié)構(gòu)數(shù)組(3) nops : opsptr所指向的數(shù)組中的sembuf結(jié)構(gòu)體的個數(shù)struct sembuf short sem_num; / 要操作的信號量在信號量集里的編號, short sem_op; / 信號量操作 short sem_flg; / 操作表示符;(4) 假設(shè)sem_op 是正數(shù),其值就加到semval上,即釋放信號量控制的資源 假設(shè)sem_op 是0,那么調(diào)用者希望等到semval變?yōu)?,如果semval是0就返回;假設(shè)sem_o

41、p 是負(fù)數(shù),那么調(diào)用者希望等待semval變?yōu)榇笥诨虻扔趕em_op的絕對值例如,當(dāng)前semval為2,而sem_op = -3,那么怎么辦?注意:semval是指semid_ds中的信號量集中的某個信號量的值(5) sem_flg SEM_UNDO 由進程自動釋放信號量 IPC_NOWAIT 不阻塞到這里,讀者肯定有個疑惑:semop希望改變的semval到底在哪里?我們怎么沒看到有它的痕跡?其實,前面已經(jīng)說明了,當(dāng)使用semget時,就產(chǎn)生了一個由內(nèi)核維護的信號量集當(dāng)然每個信號量值即semval也是只由內(nèi)核才能看得到了,用戶能看到的就是返回的semid。內(nèi)核通過semop函數(shù)的參數(shù),知道應(yīng)

42、該去改變semid所指向的信號量的哪個semval。e對信號集實行控制操作semval的賦值等int semctl(int semid, int semum, int cmd, ./* union semun arg */);semid是信號量集合;semnum是信號在集合中的序號;semum是一個必須由用戶自定義的結(jié)構(gòu)體,在這里我們務(wù)必弄清楚該結(jié)構(gòu)體的組成:union semun int val; / cmd = SETVAL struct semid_ds *buf / cmd = IPC_SET或者 cmd = IPC_STAT ushort *array; / cmd = SETALL

43、,或 cmd = GETALL ;val只有cmd =SETVAL時才有用,此時指定的semval = arg.val。注意:當(dāng)cmd = GETVAL時,semctl函數(shù)返回的值就是我們想要的semval。千萬不要以為指定的semval被返回到arg.val中。 array指向一個數(shù)組,當(dāng)cmd=SETALL時,就根據(jù);當(dāng)cmd =GETALL時,就將信號量集的所有值返回到arg.array指定的數(shù)組中。buf指針只在cmd=IPC_STAT或IPC_SET時有用,作用是semid所指向的信號量集semid_ds機構(gòu)體。一般情況下不常用,這里不做談?wù)摗A硗?,cmd = IPC_RMID還是比

44、較有用的。f例碼#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#include <stdio.h>static int nsems;static int semflg;static int semid;int errno=0;union semun int val; struct semid_ds *buf; unsigned short *array; arg;int main()struct sembuf sops2; /要用到兩個信號量,所以要定義兩個操作數(shù)組in

45、t rslt;unsigned short argarray80; arg.array = argarray; semid = semget(IPC_PRIVATE, 2, 0666); if(semid < 0 ) printf("semget failed. errno: %dn", errno); exit(0); /獲取0th信號量的原始值rslt = semctl(semid, 0, GETVAL);printf("val = %dn",rslt); /初始化0th信號量,然后再讀取,檢查初始化有沒有成功arg.val = 1; / 同一

46、時間只允許一個占有者semctl(semid, 0, SETVAL, arg); rslt = semctl(semid, 0, GETVAL);printf("val = %dn",rslt); sops0.sem_num = 0;sops0.sem_op = -1; sops0.sem_flg = 0; sops1.sem_num = 1; sops1.sem_op = 1; sops1.sem_flg = 0;rslt=semop(semid, sops, 1); /申請0th信號量,嘗試鎖定 if (rslt < 0 ) printf("semop

47、failed. errno: %dn", errno); exit(0);/可以在這里對資源進行鎖定sops0.sem_op = 1;semop(semid, sops, 1); /釋放0th信號量 rslt = semctl(semid, 0, GETVAL);printf("val = %dn",rslt); rslt=semctl(semid, 0, GETALL, arg); if (rslt < 0) printf("semctl failed. errno: %dn", errno); exit(0);printf("val1:%d val2: %dn",(unsigned int)argarray0,(unsigned int)argarray1);if(semctl(semid, 1, IPC_RMID) = -1) Perror(“semctl f

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論