• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Prayer

            在一般中尋求卓越
            posts - 1256, comments - 190, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

            信號量函數(shù) semget() semop() semctl()

            Posted on 2009-03-05 15:30 Prayer 閱讀(2811) 評論(0)  編輯 收藏 引用 所屬分類: LINUX/UNIX/AIX

            問共享資源進(jìn)行控制的機(jī)制,其實(shí)為了解決互斥共享資源的同步問題而引入的機(jī)制。
            不能單獨(dú)定義一個(gè)信號量,而只能定義一個(gè)信號量集,其中包括一組信號量,同意信號量集中的信號量使用同
            一引用ID,這樣設(shè)置是為了多個(gè)資源或同步操作的需要。
            與信號量有關(guān)的幾個(gè)系統(tǒng)調(diào)用函數(shù):
            1、信號量集得創(chuàng)建與打開 semget()
            原型:int semget(key_t key,int nsems,int semflg);
            其中 參數(shù)key表示所創(chuàng)建或打開信號量集的鍵。
            參數(shù)nsems表示創(chuàng)建的信號量集中的信號量的個(gè)數(shù),該參數(shù)只在創(chuàng)建信號量集時(shí)有效。
            參數(shù)flag表示調(diào)用函數(shù)的操作類型,也可用于設(shè)置信號量集的訪問權(quán)限,兩者通過or表示。
            當(dāng)調(diào)用semget創(chuàng)建一個(gè)信號量時(shí),他的相應(yīng)的semid_ds結(jié)構(gòu)被初始化。ipc_perm中各個(gè)量被設(shè)置為相應(yīng)
            值,sem_nsems被設(shè)置為nsems所示的值,sem_otime被設(shè)置為0,sem_ctime被設(shè)置為當(dāng)前時(shí)間
            返回值:如果成功,則返回信號量集的IPC標(biāo)識(shí)符。如果失敗,則返回-1:errno=EACCESS(沒有權(quán)限)
            EEXIST(信號量集已經(jīng)存在,無法創(chuàng)建)
            EIDRM(信號量集已經(jīng)刪除)
            ENOENT(信號量集不存在,同時(shí)沒有使用IPC_CREAT)
            ENOMEM(沒有足夠的內(nèi)存創(chuàng)建新的信號量集)
            ENOSPC(超出限制)
            系統(tǒng)調(diào)用semget()的第一個(gè)參數(shù)是關(guān)鍵字值(一般是由系統(tǒng)調(diào)用ftok()返回的)。系統(tǒng)內(nèi)核將此值和系統(tǒng)中
            存在的其他的信號量集的關(guān)鍵字值進(jìn)行比
            較。打開和存取操作與參數(shù)semflg中的內(nèi)容相關(guān)。IPC_CREAT如果
            信號量集在系統(tǒng)內(nèi)核中不存在,則創(chuàng)建信號量集。IPC_EXCL當(dāng)和
            IPC_CREAT一同使用時(shí),如果信號量集已經(jīng)
            存在,則調(diào)用失敗。如果單獨(dú)使用IPC_CREAT,則semget()要么返回新創(chuàng)建的信號量集的標(biāo)識(shí)
            符,要么返回
            系統(tǒng)中已經(jīng)存在的同樣的關(guān)鍵字值的信號量的標(biāo)識(shí)符。如果IPC_EXCL和IPC_CREAT一同使用,則要么返回新
            創(chuàng)建的信號量集的標(biāo)識(shí)
            符,要么返回-1。IPC_EXCL單獨(dú)使用沒有意義。參數(shù)nsems指出了一個(gè)新的信號量集
            中應(yīng)該創(chuàng)建的信號量的個(gè)數(shù)。
            2、信號量的操作 semop()
            調(diào)用原型:int semop(int semid,struct sembuf*sops,unsign ednsops);
            其中   semid為信號量集引用ID。
                semoparray是一個(gè)sembuff結(jié)構(gòu)數(shù)組,sembuff結(jié)構(gòu)用于指定調(diào)用semop函數(shù)所作的操作,數(shù)組
                semoparray元素的個(gè)數(shù)有參數(shù)nops指出。
                semoparray是一個(gè)數(shù)組,其中每個(gè)元素表是一個(gè)操作,由于此函數(shù)是一個(gè)原子操作,一旦執(zhí)行就
            將執(zhí)行數(shù)組中的所有操作。
            返回值:0,如果成功。-1,如果失敗:errno=E2BIG(nsops大于最大的ops數(shù)目)
            EACCESS(權(quán)限不夠)
            EAGAIN(使用了IPC_NOWAIT,但操作不能繼續(xù)進(jìn)行)
            EFAULT(sops指向的地址無效)
            EIDRM(信號量集已經(jīng)刪除)
            EINTR(當(dāng)睡眠時(shí)接收到其他信號)
            EINVAL(信號量集不存在,或者semid無效)
            ENOMEM(使用了SEM_UNDO,但無足夠的內(nèi)存創(chuàng)建所需的數(shù)據(jù)結(jié)構(gòu))
            ERANGE(信號量值超出范圍)
            如果sem_op是負(fù)數(shù),那么信號量將減去它的值。這和信號量控制的資源有關(guān)。如果沒有使用IPC_NOWAIT,
            那么調(diào)用進(jìn)程將進(jìn)入睡眠狀態(tài),直到信號
            量控制的資源可以使用為止。如果sem_op是正數(shù),則信號量加上
            它的值。這也就是進(jìn)程釋放信號量控制的資源。最后,如果sem_op是0,那么調(diào)用進(jìn)程
            將調(diào)用sleep(),
            直到信號量的值為0。這在一個(gè)進(jìn)程等待完全空閑的資源時(shí)使用。
            3、信號量的控制 semctl()
            原型:int semctl(int semid,int semnum,int cmd,union semun arg);
            其中   semid為信號量集引用標(biāo)志符。
                semnum用于指定某個(gè)特定信號量。
                cmd表示調(diào)用該函數(shù)執(zhí)行的操作,其取值和對應(yīng)操作如下:
                  .IPC_STAT讀取一個(gè)信號量集的數(shù)據(jù)結(jié)構(gòu)semid_ds,并將其存儲(chǔ)在semun中的buf參數(shù)中。
                  ·IPC_SET設(shè)置信號量集的數(shù)據(jù)結(jié)構(gòu)semid_ds中的元素ipc_perm,其值取自semun中的buf參數(shù)。
                  ·IPC_RMID將信號量集從內(nèi)存中刪除。
                  ·GETALL用于讀取信號量集中的所有信號量的值。
                  ·GETNCNT返回正在等待資源的進(jìn)程數(shù)目。
                  ·GETPID返回最后一個(gè)執(zhí)行semop操作的進(jìn)程的PID。
                  ·GETVAL返回信號量集中的一個(gè)單個(gè)的信號量的值。
                  ·GETZCNT返回這在等待完全空閑的資源的進(jìn)程數(shù)目。
                  ·SETALL設(shè)置信號量集中的所有的信號量的值。
                  ·SETVAL設(shè)置信號量集中的一個(gè)單獨(dú)的信號量的值。
            arg是semnu的是一個(gè)聯(lián)合類型的副本,而不是一個(gè)指向聯(lián)合類型的指針。聯(lián)合中各個(gè)量的使用情況
            和參數(shù)cmd的設(shè)置有關(guān)。

            參考文獻(xiàn):linux環(huán)境下C編程指南
                  http://qq164587043.blog.51cto.com/261469/51549

            semget()

                 可以使用系統(tǒng)調(diào)用semget()創(chuàng)建一個(gè)新的信號量集,或者存取一個(gè)已經(jīng)存在的信號量集:
            系統(tǒng)調(diào)用:semget();
            原型:intsemget(key_t key,int nsems,int semflg);
            返回值:如果成功,則返回信號量集的IPC標(biāo)識(shí)符。如果失敗,則返回-1:errno=EACCESS(沒有權(quán)限)
            EEXIST(信號量集已經(jīng)存在,無法創(chuàng)建)
            EIDRM(信號量集已經(jīng)刪除)
            ENOENT(信號量集不存在,同時(shí)沒有使用IPC_CREAT)
            ENOMEM(沒有足夠的內(nèi)存創(chuàng)建新的信號量集)
            ENOSPC(超出限制)
                系統(tǒng)調(diào)用semget()的第一個(gè)參數(shù)是關(guān)鍵字值(一般是由系統(tǒng)調(diào)用ftok()返回的)。系統(tǒng)內(nèi)核將此值和系統(tǒng)中存在的其他的信號量集的關(guān)鍵字值進(jìn)行比 較。打開和存取操作與參數(shù)semflg中的內(nèi)容相關(guān)。IPC_CREAT如果信號量集在系統(tǒng)內(nèi)核中不存在,則創(chuàng)建信號量集。IPC_EXCL當(dāng)和 IPC_CREAT一同使用時(shí),如果信號量集已經(jīng)存在,則調(diào)用失敗。如果單獨(dú)使用IPC_CREAT,則semget()要么返回新創(chuàng)建的信號量集的標(biāo)識(shí) 符,要么返回系統(tǒng)中已經(jīng)存在的同樣的關(guān)鍵字值的信號量的標(biāo)識(shí)符。如果IPC_EXCL和IPC_CREAT一同使用,則要么返回新創(chuàng)建的信號量集的標(biāo)識(shí) 符,要么返回-1。IPC_EXCL單獨(dú)使用沒有意義。參數(shù)nsems指出了一個(gè)新的信號量集中應(yīng)該創(chuàng)建的信號量的個(gè)數(shù)。信號量集中最多的信號量的個(gè)數(shù)是 在linux/sem.h中定義的:
            #defineSEMMSL32/*<=512maxnumofsemaphoresperid*/
            下面是一個(gè)打開和創(chuàng)建信號量集的程序:
            intopen_semaphore_set(key_t keyval,int numsems)
            {
            intsid;
            if(!numsems)
            return(-1);
            if((sid=semget(mykey,numsems,IPC_CREAT|0660))==-1)
            {
            return(-1);
            }
            return(sid);
            }
            };
            ==============================================================
            semop()

            系統(tǒng)調(diào)用:semop();
            調(diào)用原型:int semop(int semid,struct sembuf*sops,unsign ednsops);
            返回值:0,如果成功。-1,如果失敗:errno=E2BIG(nsops大于最大的ops數(shù)目)
            EACCESS(權(quán)限不夠)
            EAGAIN(使用了IPC_NOWAIT,但操作不能繼續(xù)進(jìn)行)
            EFAULT(sops指向的地址無效)
            EIDRM(信號量集已經(jīng)刪除)
            EINTR(當(dāng)睡眠時(shí)接收到其他信號)
            EINVAL(信號量集不存在,或者semid無效)
            ENOMEM(使用了SEM_UNDO,但無足夠的內(nèi)存創(chuàng)建所需的數(shù)據(jù)結(jié)構(gòu))
            ERANGE(信號量值超出范圍)
                第一個(gè)參數(shù)是關(guān)鍵字值。第二個(gè)參數(shù)是指向?qū)⒁僮鞯臄?shù)組的指針。第三個(gè)參數(shù)是數(shù)組中的操作的個(gè)數(shù)。參數(shù)sops指向由sembuf組成的數(shù)組。此數(shù)組是在linux/sem.h中定義的:
            /*semop systemcall takes an array of these*/
            structsembuf{
            ushortsem_num;/*semaphore index in array*/
            shortsem_op;/*semaphore operation*/
            shortsem_flg;/*operation flags*/
            sem_num將要處理的信號量的個(gè)數(shù)。
            sem_op要執(zhí)行的操作。
            sem_flg操作標(biāo)志。
                如果sem_op是負(fù)數(shù),那么信號量將減去它的值。這和信號量控制的資源有關(guān)。如果沒有使用IPC_NOWAIT,那么調(diào)用進(jìn)程將進(jìn)入睡眠狀態(tài),直到信號 量控制的資源可以使用為止。如果sem_op是正數(shù),則信號量加上它的值。這也就是進(jìn)程釋放信號量控制的資源。最后,如果sem_op是0,那么調(diào)用進(jìn)程 將調(diào)用sleep(),直到信號量的值為0。這在一個(gè)進(jìn)程等待完全空閑的資源時(shí)使用。
            ===============================================================
            semctl()

            系統(tǒng)調(diào)用:semctl();
            原型:int semctl(int semid,int semnum,int cmd,union semunarg);
            返回值:如果成功,則為一個(gè)正數(shù)。
            如果失敗,則為-1:errno=EACCESS(權(quán)限不夠)
            EFAULT(arg指向的地址無效)
            EIDRM(信號量集已經(jīng)刪除)
            EINVAL(信號量集不存在,或者semid無效)
            EPERM(EUID沒有cmd的權(quán)利)
            ERANGE(信號量值超出范圍)
                系統(tǒng)調(diào)用semctl用來執(zhí)行在信號量集上的控制操作。這和在消息隊(duì)列中的系統(tǒng)調(diào)用msgctl是十分相似的。但這兩個(gè)系統(tǒng)調(diào)用的參數(shù)略有不同。因?yàn)樾盘? 量一般是作為一個(gè)信號量集使用的,而不是一個(gè)單獨(dú)的信號量。所以在信號量集的操作中,不但要知道IPC關(guān)鍵字值,也要知道信號量集中的具體的信號量。這兩 個(gè)系統(tǒng)調(diào)用都使用了參數(shù)cmd,它用來指出要操作的具體命令。兩個(gè)系統(tǒng)調(diào)用中的最后一個(gè)參數(shù)也不一樣。在系統(tǒng)調(diào)用msgctl中,最后一個(gè)參數(shù)是指向內(nèi)核 中使用的數(shù)據(jù)結(jié)構(gòu)的指針。我們使用此數(shù)據(jù)結(jié)構(gòu)來取得有關(guān)消息隊(duì)列的一些信息,以及設(shè)置或者改變隊(duì)列的存取權(quán)限和使用者。但在信號量中支持額外的可選的命 令,這樣就要求有一個(gè)更為復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。
            系統(tǒng)調(diào)用semctl()的第一個(gè)參數(shù)是關(guān)鍵字值。第二個(gè)參數(shù)是信號量數(shù)目。
                參數(shù)cmd中可以使用的命令如下:
                ·IPC_STAT讀取一個(gè)信號量集的數(shù)據(jù)結(jié)構(gòu)semid_ds,并將其存儲(chǔ)在semun中的buf參數(shù)中。
                ·IPC_SET設(shè)置信號量集的數(shù)據(jù)結(jié)構(gòu)semid_ds中的元素ipc_perm,其值取自semun中的buf參數(shù)。
                ·IPC_RMID將信號量集從內(nèi)存中刪除。
                ·GETALL用于讀取信號量集中的所有信號量的值。
                ·GETNCNT返回正在等待資源的進(jìn)程數(shù)目。
                ·GETPID返回最后一個(gè)執(zhí)行semop操作的進(jìn)程的PID。
                ·GETVAL返回信號量集中的一個(gè)單個(gè)的信號量的值。
                ·GETZCNT返回這在等待完全空閑的資源的進(jìn)程數(shù)目。
                ·SETALL設(shè)置信號量集中的所有的信號量的值。
                ·SETVAL設(shè)置信號量集中的一個(gè)單獨(dú)的信號量的值。
                參數(shù)arg代表一個(gè)semun的實(shí)例。semun是在linux/sem.h中定義的:
            /*arg for semctl systemcalls.*/
            unionsemun{
            intval;/*value for SETVAL*/
            structsemid_ds*buf;/*buffer for IPC_STAT&IPC_SET*/
            ushort*array;/*array for GETALL&SETALL*/
            structseminfo*__buf;/*buffer for IPC_INFO*/
            void*__pad;
                val當(dāng)執(zhí)行SETVAL命令時(shí)使用。buf在IPC_STAT/IPC_SET命令中使用。代表了內(nèi)核中使用的信號量的數(shù)據(jù)結(jié)構(gòu)。array在使用GETALL/SETALL命令時(shí)使用的指針。
                下面的程序返回信號量的值。當(dāng)使用GETVAL命令時(shí),調(diào)用中的最后一個(gè)參數(shù)被忽略:
            intget_sem_val(intsid,intsemnum)
            {
            return(semctl(sid,semnum,GETVAL,0));
            }
                下面是一個(gè)實(shí)際應(yīng)用的例子:
            #defineMAX_PRINTERS5
            printer_usage()
            {
            int x;
            for(x=0;x<MAX_PRINTERS;x++)
            printf("Printer%d:%d\n\r",x,get_sem_val(sid,x));
            }
                下面的程序可以用來初始化一個(gè)新的信號量值:
            void init_semaphore(int sid,int semnum,int initval)
            {
            union semunsemopts;
            semopts.val=initval;
            semctl(sid,semnum,SETVAL,semopts);
            }
                注意系統(tǒng)調(diào)用semctl中的最后一個(gè)參數(shù)是一個(gè)聯(lián)合類型的副本,而不是一個(gè)指向聯(lián)合類型的指針。
            九九久久精品国产| 久久精品国产亚洲AV蜜臀色欲 | 亚洲AV无码久久| 亚洲色大成网站WWW久久九九| 亚洲国产另类久久久精品| 久久免费视频观看| 色婷婷综合久久久久中文字幕| 狠狠色丁香久久婷婷综合蜜芽五月 | 久久久99精品成人片中文字幕| 久久婷婷五月综合97色直播 | 一级a性色生活片久久无| 精品久久久久久中文字幕大豆网| 狠狠色噜噜狠狠狠狠狠色综合久久| 99久久综合国产精品二区| 午夜精品久久久久| 久久国产香蕉一区精品| 亚洲精品无码久久久久久| 久久人人爽人爽人人爽av| 精品久久久久久中文字幕人妻最新| 久久人人爽人爽人人爽av| 精品精品国产自在久久高清| 精品久久亚洲中文无码| 久久夜色精品国产噜噜亚洲a| 久久99国产精品一区二区| 亚洲综合精品香蕉久久网| 伊人久久大香线蕉综合5g| 国産精品久久久久久久| 国产精品天天影视久久综合网| 亚洲国产一成人久久精品| 精品久久亚洲中文无码| 亚洲婷婷国产精品电影人久久| 9999国产精品欧美久久久久久| 国产Av激情久久无码天堂| 久久99精品久久久久久hb无码 | 九九精品99久久久香蕉| 日韩精品久久久久久免费| 亚洲AV无一区二区三区久久| 精品多毛少妇人妻AV免费久久| 亚洲国产精品综合久久网络| 中文国产成人精品久久亚洲精品AⅤ无码精品| 久久福利青草精品资源站|