国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

查看: 2839|回復: 1
打印 上一主題 下一主題

【武漢華嵌】Linux進程間通信之信號量

[復制鏈接]
跳轉到指定樓層
樓主
發表于 2011-11-1 15:02:11 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
作者:武漢華嵌 嵌入式培訓中心技術部

信號量是一種用于提供不同進程間或一個給定進程的不同線程間同步手段的原語。在UNIX下有三種分別如下:
  • Posix有名信號量;
  • Posix基于內存的信號量;
  • System V信號量。
在這里只和大家分享下有關System V信號量。
System V通過定義計數信號量集來對信號量的操作,計數信號量集是一個或多個信號量構成一個集合,其中每個都是計數信號量。對于系統中的每個信號量集,內核維護一個如下的信息結構,它定義在頭文件中。
struct semid_ds{
struct ipc_perm  sem_perm;     /* operation permission struct */
struct sem      *sem_base;     /* ptr to array of semaphores in set */
uishort          sem_nsems;    /* #of semaphores in set */
time_t          sem_otime;    /* time of last semop() */
time_t          sem_ctime;    /* time of creation or last IPC_SET */
};

成員struct sem結構如下:
         struct sem{
         ushort_t   semval;    /* semaphore value , nonnegative */
         short      sempid;    /* PID of last successful semop(), SETVAL, SETALL */
         ushort_t   semncnt;   /* awaiting semval > current value */
         ushort_t   semzcnt;    /* awaiting semval = 0 */
         };

注意在struct semid_ds結構中的sem_base含有指向某個sem結構數組的指針:當前信號量集中的每個信號對應其中一個數組元素。我們可以把內核中的某個選定信號量圖解成指向一個sem結構數組的一個semid_ds結構。圖解如下:
file:///C:/DOCUME~1/jack/LOCALS~1/Temp/msohtml1/01/clip_image001.png
有了以上的理論,那么接下來我們來探討下如何對這樣的信號量進行操作,linux操作系統為我們提供了操作system v信號量的API函數,以下就開始講解這些API函數。
  • semget函數創建一個信號量集或訪問一個已存在的信號量集。
#include
int semget(key_t key, int nsems, int oflag);
該函數成功返回時,其返回值是一個稱為信號量標識符的整數,semop和semctl使用它。出錯則返回-1。
nsems參數指定集合中的信號量數。如果我們創建一個新的信號量集,而只是訪問一個已存在的集合,那就可以把該參數指定為0。一旦創建完一個信號量集,我們就不能改變其中的信號量數。
oflag值是一些權限值的組合,如果是創建一個信號量集,那么得在此oflag的基礎上或上O_CREAT或者是O_CREAT|O_EXCL。
此函數不可以對創建的信號量集中的信號量進行初始化,對信號量的初始化是通過另外的一個函數semctl進行的。
  • 通過semctl函數對信號量集中的信號量進行初始化。
#include
int semctl(int semid, int semnum, int cmd, …./* union semun arg*/ );
         semid標識其操作待控制的信號量集。
         semnum標識該信號量集內的某個成員(0, 1等待,直到nsems -1)。semnum值僅僅用于GETVAL、SETVAL、GETNCNT、GETZCNT和GETPID命令。
         第四個參數是可選的,取決于第三個參數cmd。union semnu結構如下:
union semnu{
         int              val;     /* used for SETVAL only */
         struct semid_ds   *buf;    /* used for IPC_SET and IPC_STAT */
         ushort          *array;   /* used for GETALL and SETALL */
         };
         這個聯合體并沒有出現在任何頭文件中,因而必須由應用程序聲明。
第三個參數cmd可以取以下值:
GETVAL  把semval的當前值作為函數返回值返回。
SETVAL  把semval值設置為arg.val。如果操作成功,那么相應信號量在所有進程是的信號
                   量調整值(semadj)將被置為0。
IPC_RMID 把由semid指定的信號量集從系統中刪除掉。
IPC_SET 設置所指定信號量集的semid_ds結構中的某些成員。
IPC_SET R 返回所指定信號量集當前的semid_ds結構。
  • 使用semget得到一個信號量集,使用semctl設置信號量集中的信號量,那么對信號量集中的信號通過semop來進行操作。
#include
int semop(int semid, struct sembuf *opsptr, size_t nops);
semid標識其操作的信號量集。
其中opsptr指向一個如下結構的數組:
Struct sembuf{
Short    sem_num;     /* semaphore number: 0, 1, …., nsems-1 */
Short    sem_op;      /* semaphore operation: <0, 0, >0 */
Short    sem_flag;     /* semaphore flags : 0, IPC_NOWAITE, SEM_UNDO */
};
nops參數指出由opsptr指向的sembuf結構數組中元素的數目。該數組中的生個元素給目標信號量集內某個特定的信號量指定一個操作。這個特定的信號量由sem)num指定,0代表第一個元素,1代表第二個元素,依次類推,直到nsems-1,其中nsems是目標信號量集內成員信號量的數目。
semop對信號的操作是由sem_op的值確定的,以下是對sem_op取值的分析:
  • 、sem_op 為正數時,會把sem_op的值加到操作的信號量的信號值上。如果sem_flg被設置為IPC_UNDO,無論程序正常結束與否,都會把信號值重新設置為調用semop函數前得值。這對應于進程釋放占用的資源數。
  • 、sem_op為負數時,如果要操作的信號量的值大于或者等于sem_op的絕對值,則從信號量值中加上sen_op的值。如果信號量值小于sem_op的絕對值,則有如下:
    • 如果sem_flg的值為IPC_NOWAIT,那么semop出錯,返回EAGAIN。
    • 如果sem_flg沒有設置為IPC_NOWAIT,則該信號量的semncnt的值加1,然后此進程掛起,直到此信號量的值大于sem_op的絕對值,才執行semop操作;或者此信號量從系統中刪除,此時semop返回EIDRM;或者該掛起進程捕捉到信號,從信號處理程序返回,此時,semop出錯返回EINTR。
    • 如果sen_op的值為0,則調用進程希望等到該信號量值變成0。
  • 、sem_op為0時,那么調用者希望等待到semval變為0。如果sem_op已經是0,那就立即返回。

以下是利用信號量來進行一個PV操作,實現代碼如下:

//初始化信號量
int init_sem(int semid, int semval)
{
         SYS_NUM semnu;
         semnu.sem_val = semval;
         if((semctl(semid, 0, SETVAL, semnu)) < 0)
         {
                   perror("init_sem semctl");
                   return -1;
         }
         return 0;
}

//對信號量進行p操作
int sem_p(int semid)
{
         SYS_SEM sembu;

         sembu.sem_num = 0;
         sembu.sem_op = -1;
         sembu.sem_flg = SEM_UNDO;

         if((semop(semid, &sembu, 1)) < 0)
         {
                   perror("sem_p semop");
                   return -1;
         }
         return 0;
}

//對信號量進行v操作
int sem_v(int semid)
{
         SYS_SEM sembu;

         sembu.sem_num = 0;
         sembu.sem_op = 1;
         sembu.sem_flg = SEM_UNDO;

         if((semop(semid, &sembu, 1)) < 0)
         {
                   perror("sem_v semop");
                   return -1;
         }
         return 0;
}

//刪除信號量集
int del_sem(int semid)
{
         if((semctl(semid, 0, IPC_RMID)) < 0)
         {
                   perror("del_sem semctl");
                   return -1;
         }
         return 0;
}


總結:
         信號量往往是用來同步的,保護共享內存。

更多技術文章敬請關注:武漢華嵌-嵌入式培訓專家,國內領先的嵌入式服務機構,
http://www.embedhq.org
沙發
 樓主| 發表于 2013-4-8 14:34:44 | 只看該作者
武漢華嵌嵌入式培訓
咨詢QQ:1216677636   
        QQ:572658958
咨詢電話:027-87780211
您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲国产天堂久久九九九| 亚洲国产精品综合欧美| 亚洲精品久久77777| 最新91在线| 国产精品资源网站在线观看| 奇米精品一区二区三区在线观看 | 亚洲美女爱爱| 亚洲视频一区二区在线观看| 成人免费公开视频| 欧美伊人久久大香线蕉综合69 | 亚洲成a人片在线观看导航| 色综合久久综合欧美综合网| 五月婷婷六月综合| 午夜亚洲国产| 2020国产欧洲精品视频| 久久re热线视频国产| 亚洲色欲色欲www474ee| 一本加勒比dvd波多野结衣| 天天躁夜夜躁狠狠躁2024| 婷综合| [高清无码] 波多野结衣| 久久精品综合电影| 四虎精品成人免费观看| 日本成人在线免费| 在线视频a| 97视频久久| 奶头被客人吸得又红又肿| 最近韩国日本免费观看mv免费版| 四虎影视永久免费| 亚洲乱码一二三四区乱码| 在线男人天堂| 久久精品亚洲AV无码三区观看| 亚洲国产成人久久午夜| 日韩黄色毛片| 特黄一级真人毛片| 99国内偷揿国产精品人妻| 少妇被躁爽到高潮无码久久| 日韩美女在线观看| 日日日日人人人夜夜夜2017| 亚洲国产m3u8在线观看| 高h乱一受多攻男男|