1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢
      選擇下列產(chǎn)品馬上在線溝通
      服務(wù)時(shí)間:8:30-17:00
      你可能遇到了下面的問題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
      信號量(semaphore)

      進(jìn)程間通信-信號量

      創(chuàng)新互聯(lián)專業(yè)成都做網(wǎng)站、網(wǎng)站設(shè)計(jì),集網(wǎng)站策劃、網(wǎng)站設(shè)計(jì)、網(wǎng)站制作于一體,網(wǎng)站seo、網(wǎng)站優(yōu)化、網(wǎng)站營銷、軟文發(fā)布平臺(tái)等專業(yè)人才根據(jù)搜索規(guī)律編程設(shè)計(jì),讓網(wǎng)站在運(yùn)行后,在搜索中有好的表現(xiàn),專業(yè)設(shè)計(jì)制作為您帶來效益的網(wǎng)站!讓網(wǎng)站建設(shè)為您創(chuàng)造效益。


      1、為什么要使用信號量

      為了防止多個(gè)程序同時(shí)訪問一個(gè)共享資源而引發(fā)的一系列問題,故有這樣一種方法,在任何一個(gè)時(shí)刻只有一個(gè)執(zhí)行線程訪問代碼的臨界區(qū)(臨界區(qū)是指訪問臨界資源的代碼),而信號量就可以提供這樣的訪問機(jī)制,同一時(shí)刻只允許一個(gè)線程訪問臨界區(qū),也就是說信號量是用來協(xié)調(diào)進(jìn)程共享資源訪問的,也就是說信號量用來協(xié)調(diào)進(jìn)程對共享資源訪問的,其中共享內(nèi)存就是用信號量實(shí)現(xiàn)的。

      2、信號量的工作原理

      由于信號量只能進(jìn)行兩種操作等待和發(fā)送信號,他們是p(sv)操作,v(sv)操作。

      p(sv)操作:如果sv的值大于0.他就減1,如果sv的值等于0,它就掛起進(jìn)程的執(zhí)行。

      v(sv)操作:如果有其他進(jìn)程因等待sv而掛起,則就讓他恢復(fù)運(yùn)行,如果沒有進(jìn)程因等待它而掛起,就讓他加1.

      舉個(gè)例子,就是 兩個(gè)進(jìn)程共享信號量sv,一旦其中一個(gè)進(jìn)程執(zhí)行了P(sv)操作,它將得到信號量,并可以進(jìn)入臨界區(qū),使sv減1。而第二個(gè)進(jìn)程將被阻止進(jìn)入臨界區(qū),因?yàn)? 當(dāng)它試圖執(zhí)行P(sv)時(shí),sv為0,它會(huì)被掛起以等待第一個(gè)進(jìn)程離開臨界區(qū)域并執(zhí)行V(sv)釋放信號量,這時(shí)第二個(gè)進(jìn)程就可以恢復(fù)執(zhí)行。

      3、Linux信號量機(jī)制

      Linux提供了一組精心設(shè)置的信號量接口來對信號量進(jìn)行操作。這些函數(shù)都是用來對組的信號量進(jìn)行操作,他們被聲明在sys/sem.h中。

      4、信號量的使用

      (1)創(chuàng)建信號量

      semget函數(shù)創(chuàng)建一個(gè)信號量集或者訪問一個(gè)已存在的信號量集

      int semget (key_t key, int nsem, int oflag)

      返回值是一個(gè)稱為信號量標(biāo)識(shí)符的整數(shù),semop和semctl函數(shù)將使用它。成功返回信號量的標(biāo)示符,失敗返回-1

      key:由ftok()函數(shù)得到,

      nsem:創(chuàng)建信號量中的個(gè)數(shù)

      oflag:

          IPC_CREAT:若內(nèi)核中不存在鍵值與key相等的信號量集,則創(chuàng)建,否則,返回此信號量集的標(biāo)識(shí)符

          IPC_EXCL:單獨(dú)使用無意義

          IPC_CREAT | IPC_EXCL :創(chuàng)建一個(gè)新的信號量集并返回信號量集的標(biāo)識(shí)符,否則,返回-1.

      (2)打開信號量(完成對信號量的PV操作)

      用semget打開一個(gè)信號量后,對其中一個(gè)或多個(gè)信號量操作就是用semop來執(zhí)行。

      int semop (int semid, struct sembuf * opsptr, size_t nops)

          semid:信號量集標(biāo)識(shí)符

          nsops:進(jìn)行操作信號量的個(gè)數(shù),即sops結(jié)構(gòu)變量的個(gè)數(shù),需大于或等于1.

          opspt:是一個(gè)指針,它指向一個(gè)信號量操作數(shù)組,信號量操作由sembuf結(jié)構(gòu)表示

      struct sembuf{
       short sem_num; // 除非使用一組信號量,否則它為0 
       short sem_op; // 信號量在一次操作中需要改變的數(shù)據(jù),通常是兩個(gè)數(shù),
       // 一個(gè)是-1,即P(等待)操作,一個(gè)是+1,即V(發(fā)送信號)操作 
       short sem_flg; // 通常為SEM_UNDO,使操作系統(tǒng)跟蹤信號,并在進(jìn)程沒有釋放該信號量而終止時(shí),
       // 操作系統(tǒng)釋放信號量 
      };

       當(dāng)操作信號量(semop)時(shí),flg可以設(shè)置SEM_UNDO標(biāo)識(shí);SEM_UNDO用于將修改的信號量值在進(jìn)程正常退出(調(diào)用exit退出或main執(zhí)行完)或異常退出(如段異常、除0異常、收到KILL信號等)時(shí)歸還給信號量。進(jìn)程以SEM_UNDO方式操作后;在進(jìn)程未退出時(shí),可以改變信號量的值,在進(jìn)程退出時(shí),將修改的值歸還給信號量,信號量變成原來的值。

      (3)在指定信號集或者信號集上的某個(gè)信號進(jìn)行操作

      int semctl(int semid,int semnum,int cmd,union semun arg)

          semid: 信號量集標(biāo)識(shí)符

        semnum:信號量集數(shù)組上的下標(biāo),表示某一個(gè)信號量

      第四個(gè)參數(shù)是可選的,取決于第個(gè)信號(操作對象)

      參數(shù)cmd指定以下10種命令中的一種,在semid指定的信號量集合上執(zhí)行此命令。

      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ú)的信號量的值。

      5.例子

      comm.h

      #define _PATH_NAME_ "/tmp"
      #define _PROJ_ID_ 0x6666
      
      int create_sem_set();
      
      union semun
      {
          int val;
          struct semid_ds* buf;
          unsigned short *array;
          struct eminfo*_buf;
      };
      
      int init_sem_set(int sem_id,int which,int val);
      int create_sem_set(int nums);
      int get_sem_set();
      
      int destory_sem_set(int sem_id);
      
      int P(int sem_id,int num);
      
      int    V(int sem_id,int num);

      comm.c

      #include"comm.h"
      static int comm_sem_set(int nums,int flags)
      {
          key_t _key = ftok(_PATH_NAME_,_PROJ_ID_);
          if(_key<0)
          {
              perror("ftok");
              return -1;
          }
      //    int sem_id = semget(_key,nums,IPC_CREAT |IPC_EXCL);
          int sem_id = semget(_key,nums,flags);
          if(sem_id <0)
          {
              perror("semget");
              return -2;
          }
          return sem_id;
      }
      
      int create_sem_set(int nums)
      {
          int flags = IPC_CREAT | IPC_EXCL | 0666;
          return comm_sem_set(nums,flags);   
      }
      
      int get_sem_set()
      {    
          int flags = IPC_CREAT;
          return comm_sem_set(0,flags);
      }
      
      int destory_sem_set(int sem_id)
      {
          if(semctl(sem_id,0,IPC_RMID)<0)
          {
              perror("semctl");
          }
          return 0;
      }
      
      int init_sem_set(int sem_id,int which,int val)
      {
          union semun _un;
          _un.val = val;
          if(semctl(sem_id,which,SETVAL,_un)<0)
          {
              perror("semctl");
              return -1;
          }
      }
      static int comm_op(int sem_id,int num,int op)
      {
          struct sembuf _sembuf;
          _sembuf.sem_num = num;
          _sembuf.sem_op = op;
          _sembuf.sem_flg = 0;
      
          if(semop(sem_id,&_sembuf,1)<0)
          {
              perror("semop");
              return -1;
          }
          return 0;
      }
      
      int P(int sem_id,int num)
      {    
          int op = -1;
          return comm_op(sem_id,num,op);
      }
      
      int    V(int sem_id,int num)
      {
          int op = -1;
          return comm_op(sem_id,num,op);
      }

      test_sem.c

      #include
      #include
      #include
      #include
      
      #define _PATH_NAME_ "/tmp"
      #define _PROJ_ID_ 0x6666
      
      int create_sem_set();
      
      union semun
      {
          int val;
          struct semid_ds* buf;
          unsigned short *array;
          struct eminfo*_buf;
      };
      
      int init_sem_set(int sem_id,int which,int val);
      int create_sem_set(int nums);
      int get_sem_set();
      
      int destory_sem_set(int sem_id);
      
      int P(int sem_id,int num);
      
      int    V(int sem_id,int num);
      [lh@localhost SEM]$ ^C
      [lh@localhost SEM]$ cat comm.c
      #include"comm.h"
      
      static int comm_sem_set(int nums,int flags)
      {
          key_t _key = ftok(_PATH_NAME_,_PROJ_ID_);
      
          if(_key<0)
          {
              perror("ftok");
              return -1;
          }
      //    int sem_id = semget(_key,nums,IPC_CREAT |IPC_EXCL);
          int sem_id = semget(_key,nums,flags);
          if(sem_id <0)
          {
              perror("semget");
              return -2;
          }
          return sem_id;
      }
      
      int create_sem_set(int nums)
      {
          int flags = IPC_CREAT | IPC_EXCL | 0666;
          return comm_sem_set(nums,flags);
          
      }
      
      int get_sem_set()
      {
          
          int flags = IPC_CREAT;
          return comm_sem_set(0,flags);
      }
      
      int destory_sem_set(int sem_id)
      {
          if(semctl(sem_id,0,IPC_RMID)<0)
          {
              perror("semctl");
          }
          return 0;
      }
      
      int init_sem_set(int sem_id,int which,int val)
      {
          union semun _un;
          _un.val = val;
          if(semctl(sem_id,which,SETVAL,_un)<0)
          {
              perror("semctl");
              return -1;
          }
      }
      static int comm_op(int sem_id,int num,int op)
      {
          struct sembuf _sembuf;
          _sembuf.sem_num = num;
          _sembuf.sem_op = op;
          _sembuf.sem_flg = 0;
      
          if(semop(sem_id,&_sembuf,1)<0)
          {
              perror("semop");
              return -1;
          }
          return 0;
      }
      
      int P(int sem_id,int num)
      {    
          int op = -1;
          return comm_op(sem_id,num,op);
      }
      
      int    V(int sem_id,int num)
      {
          int op = -1;
          return comm_op(sem_id,num,op);
      }
      [lh@localhost SEM]$ ^C
      [lh@localhost SEM]$ clear
      
      [lh@localhost SEM]$ cat test_sem.c
      #include"comm.h"
      #include
      int main()
      {
          int sem_id = create_sem_set(1);
          pid_t id = fork();
          init_sem_set(sem_id,0,1);
      
          if(id ==0)
          {
              int sem_id_child = get_sem_set();
              while(1)
              {
                  P(sem_id_child,0);
                  printf("A");
                  fflush(stdout);
                  usleep(rand()%3);
                  printf("A");
                  fflush(stdout);
                  usleep(rand()%12345);
                  V(sem_id_child,0);
              }
          }
          else
          {
              while(1)
              {
                  P(sem_id,0);
                  printf("B");
                  fflush(stdout);
                  usleep(rand()%3);
                  printf("B");
                  fflush(stdout);
                  usleep(rand()%12234);
                  V(sem_id,0);
              }
              wait(NULL);
              destory_sem_set(sem_id);
          }
      
          return 0;    
      }

      信號量(semaphore)


      分享名稱:信號量(semaphore)
      文章URL:http://www.ef60e0e.cn/article/igighj.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        长汀县| 兰考县| 莒南县| 武陟县| 夏津县| 蓬溪县| 山东| 泊头市| 汤阴县| 彭泽县| 沁水县| 邵阳市| 高碑店市| 日土县| 高青县| 灵武市| 新巴尔虎右旗| 钦州市| 饶平县| 山东| 安溪县| 新民市| 溧阳市| 桃源县| 凤冈县| 墨脱县| 淳化县| 江津市| 南城县| 察哈| 永修县| 苏州市| 延寿县| 抚州市| 佳木斯市| 怀远县| 承德县| 绥阳县| 杭锦后旗| 教育| 女性|