亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 2014 | 回復: 0
打印 上一主題 下一主題

進程同步之--信號量 [復制鏈接]

論壇徽章:
0
跳轉到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2010-01-23 10:05 |只看該作者 |倒序瀏覽

                                進程間同步之--信號量
   信號量分有名和無名信號量。它們的區(qū)別和管道及命名管道的區(qū)別類似。有名信號量要求創(chuàng)建一個文件,而無名信號量則直接保存在內(nèi)存中。
一,Posix信號量
Posex信號量接口總結(見下圖):
上面一行是有名信號量,可于fifo相類比,其值保存在文件中,可用于進程和線程同步;
下面一行是無名信號量,可與pipe相類比,其值保存在內(nèi)存中,可用于進程和線程同步;
中間部分,是兩者的公用接口。
sem_open()                                sem_close(),sem_unlink()  //有名信號量
         \ |sem_wait(),sem_post()       |/
         / |sem_trywait(),sem_getvalue()|\sem_destroy()  //無名信號量
sem_init()
1.公共接口
1.1 接口函數(shù)說明
#include
int sem_wait(sem_t *sem);
    測試所指定信號量的值,它的操作是原子的。
    若sem>0,那么它減1并立即返回。
    若sem==0,則睡眠直到sem>0,此時立即減1,然后返回。   
int sem_trywait(sem_t *sem);
    其他的行為和sem_wait一樣,除了:
    若sem==0,不是睡眠,而是返回一個錯誤EAGAIN。        
int sem_post(sem_t *sem);
    把指定的信號量sem的值加1;
    呼醒正在等待該信號量的任意線程。
   
int sem_getvalue(sem_t *sem, int *sval);
    取回信號量sem的當前值,把該值保存到sval中。
    若有1個或更多的線程或進程調(diào)用sem_wait阻塞在該信號量上,該函數(shù)返回兩種值:
        1) 返回0
        2) 返回阻塞在該信號量上的進程或線程數(shù)目
    linux采用返回的第一種策略。
注意:在這些函數(shù)中,只有sem_post是信號安全的函數(shù),它是可重入函數(shù)。
1.2 接口使用的一般流程
sem_init(&sem);
sem_wait(&sem);
critical area;
sem_post(&sem);
remainder area
2.無名信號量
    無名信號量是保存在變量類型為sem_t的內(nèi)存中。
int sem_init(sem_t *sem, int pshared, unsigned int value);
    1)pshared==0 用于同一多線程的同步;
    2)若pshared>0 用于多個進程間的同步,此時sem必須放在共享內(nèi)存中。
int sem_destroy(sem_t *sem);
    只能銷毀由sem_init初始化的信號量,否則后果不可預料也。
例1:
    多線程使用信號量的簡單例子:
/*
* simple_sem_app.c
*/
#include "all.h"
/* 每個字符輸出的間隔時間 */
#define TEN_MILLION 5000000L
#define BUFSIZE 1024
void *threadout(void *args);
int main(int argc, char *argv[])
{
    int error;
       int i;
       int n;
    sem_t semlock;
       pthread_t *tids;
   
       if (argc != 2) {
           fprintf (stderr, "Usage: %s numthreads\n", argv[0]);
              return 1;
       }   
       n = atoi(argv[1]);
       tids = (pthread_t *)calloc(n, sizeof(pthread_t));
       if (tids == NULL) {
           perror("Failed to allocate memory for thread IDs");
           return 1;
       }   
       if (sem_init(&semlock, 0, 1) == -1) {
           perror("Failed to initialize semaphore");
           return 1;
       }   
       for (i = 0; i  0)    /* father break */
         break;
   snprintf(buffer, BUFSIZE,
      "i:%d  process ID:%ld  parent ID:%ld  child ID:%ld\n",
       i, (long)getpid(), (long)getppid(), (long)childpid);
   c = buffer;
   if (getnamed(argv[3], &semlockp, 1) == -1) {
      perror("Failed to create named semaphore");
      return 1;
   }
   while (sem_wait(semlockp) == -1)                         /* entry section */
       if (errno != EINTR) {
          perror("Failed to lock semlock");
          return 1;
       }
   while (*c != '\0') {                                  /* critical section */
      fputc(*c, stderr);
      c++;
      for (i = 0; i
struct semid_ds {
    struct ipc_perm sem_perm;    /* 信號量集的操作許可權限 */
    struct sem *sem_base;        /* 某個信號量sem結構數(shù)組的指針,
                                   當前信號量集中的每個信號量對應其中一個數(shù)組元素 */
    ushort sem_nsems;            /* sem_base 數(shù)組的個數(shù) */
    time_t sem_otime;            /* 最后一次成功修改信號量數(shù)組的時間 */
    time_t sem_ctime;            /* 成功創(chuàng)建時間 */
};
struct sem {
    ushort semval;        /* 信號量的當前值 */
    short  sempid;        /* 最后一次返回該信號量的進程ID號 */
    ushort semncnt;        /* 等待semval大于當前值的進程個數(shù) */
    ushort semzcnt;        /* 等待semval變成0的進程個數(shù) */
};
2, 信號量操作函數(shù)
a. 創(chuàng)建和打開信號量
int semget(key_t key, int nsems, int oflag)
(1) nsems>0  : 創(chuàng)建一個信的信號量集,指定集合中信號量的數(shù)量,一旦創(chuàng)建就不能更改。
(2) nsems==0 : 訪問一個已存在的集合
(3) 返回的是一個稱為信號量標識符的整數(shù),semop和semctl函數(shù)將使用它。
(4) 創(chuàng)建成功后一下結構被設置:
    .sem_perm 的uid和gid成員被設置成的調(diào)用進程的有效用戶ID和有效組ID
    .oflag 參數(shù)中的讀寫權限位存入sem_perm.mode
    .sem_otime 被置為0,sem_ctime被設置為當前時間
    .sem_nsems 被置為nsems參數(shù)的值
    .而于該集合中的每個信號量不初始化,這些結構是在semctl,用參數(shù)SET_VAL,SETALL初始化的。
b. 設置信號量的值
int semop(int semid, struct sembuf *opsptr, size_t nops);
(1) semid 是semget返回的semid
(2) nops : 是數(shù)組opsptr的個數(shù)
(3) opsptr : 是操作結構的數(shù)組
struct sembuf {
    short sem_num;    /* 信號量的數(shù)目: 0,1,...,nsems-1 */
    short sem_op;    /* 信號量操作 */
    short sem_flg;  /* 操作表示符 */
};
(4) 若sem_op 是正數(shù),其值就加到semval上;
    若sem_op 是0,那么調(diào)用者希望等到semval變?yōu)?,如果semval是0就反回;
    若sem_op 是負數(shù),那么調(diào)用者希望等待semval變?yōu)榇笥诨虻扔趕em_op的絕對值.
(5) sem_flg
    SEM_UNDO     由進程自動釋放信號量
    IPC_NOWAIT  不阻塞
c. 對信號量集實行控制操作
int semctl(int semid, int semnum, int cmd, ../* union semun arg */);
其中semid是信號量集合,semnum是信號在集合中的序號,
union semun
{
    int val; /* cmd == SETVAL */
    struct semid_ds *buf /* cmd == IPC_SET或者 cmd == IPC_STAT */
    ushort *array; /* cmd == SETALL, 或 cmd = GETALL */
};
cmd是控制命令,參數(shù)可選
cmd取值如下:
GETVAL, SETVAL : semid集合中semnum信號量當前的semval值
GETALL,SETALL :semid集合中所有信號量的值。
IPC_RMID:刪除semid信號量集
GETPID:返回最后成功操作該信號的進程號。
IPC_STAT:返回semid集合中的struct semid_ds結構。
例子:
/* my_sem.c */  
#include   
#include   
#include   
#include   
#include   
#include   
#include   
  
int main (int argc, char **argv)  
{  
    key_t ipckey;  
    int semid;  
    /*建立兩個信號燈結構*/  
    struct sembuf sem[2]; /* sembuf defined in sys/sem.h */  
    /* 創(chuàng)建IPC Key */  
    ipckey = ftok("/tmp/rich", 42);  
    /* 創(chuàng)建信號量. 4 == READ, 2 == ALTER */  
    semid = semget(ipckey, 1, 0666 | IPC_CREAT);  
    if (semid
               
               
               
               
               
               
               

本文來自ChinaUnix博客,如果查看原文請點:http://blog.chinaunix.net/u/28197/showart_2158275.html
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復

  

北京盛拓優(yōu)訊信息技術有限公司. 版權所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關心和支持過ChinaUnix的朋友們 轉載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP