linux進程通信-信號量使用

一、相關知識

 信號量:一個整數;
  大於或等於0時代表可供併發進程使用的資源實體數;
  小於0時代表正在等待使用臨界區的進程數;
  用於互斥的信號量初始值應大於0;
  只能通過P、V原語操作而改變;
 信號量元素組成:
  1、表示信號量元素的值;
  2、最後操作信號量元素的進程ID
  3、等待信號量元素值+1的進程數;
  4、等待信號量元素值爲0的進程數;
 
二、主要函數
 
 1.1 創建信號量
 int semget(
  key_t key,  //標識信號量的關鍵字,有三種方法:1、使用IPC——PRIVATE讓系統產生,
     // 2、挑選一個隨機數,3、使用ftok從文件路徑名中產生
  int nSemes,  //信號量集中元素個數
  int flag  //IPC_CREAT;IPC_EXCL 只有在信號量集不存在時創建
 )
 成功:返回信號量句柄
 失敗:返回-1
 
 1.2 使用ftok函數根據文件路徑名產生一個關鍵字
 key_t ftok(const char *pathname,int proj_id);
 路徑名稱必須有相應權限 
 
 1.3 控制信號量
 int semctl(
  int semid,  //信號量集的句柄
  int semnum,  //信號量集的元素數
  int cmd,  //命令
  /*union senum arg */... //  
 )
 成功:返回相應的值
 失敗:返回-1
 
 命令詳細說明:
 cmd:   IPC_RMID 刪除一個信號量
  IPC_EXCL 只有在信號量集不存在時創建
  IPC_SET 設置信號量的許可權
  SETVAL 設置指定信號量的元素的值爲 agc.val
  GETVAL 獲得一個指定信號量的值
  GETPID 獲得最後操縱此元素的最後進程ID
  GETNCNT 獲得等待元素變爲1的進程數
  GETZCNT 獲得等待元素變爲0的進程數
  
 union senum 定義如下:
 union senum{
  int val;
  struct semid_ds *buf;
  unsigned short * array;
 }agc;


 其中 semid_ds 定義如下:
 struct semid_ds{
  struct ipc_pem sem_pem;  //operation pemission struct
  time_t sem_otime;  //last semop()time
  time_t sem_ctime;  //last time changed by semctl()
  struct sem *sembase;  //ptr to first semaphore in array
  struct sem_queue *sem_pending; //pending operations
  struct sem_queue *sem_pending_last; //last pending operations
  struct sem_undo *undo;  //undo requests on this arrary
  unsigned short int sem_nsems; //number of semaphores in set
 };
  
 1.4 對信號量 +1 或 -1 或測試是否爲0
 int semop(
  int semid, 
  struct sembuf *sops, //指向元素操作數組
  unsigned short nsops //數組中元素操作的個數
 )
 
 結構 sembuf 定義
 sembuf{
  short int sem_num; //semaphore number
  short int sem_op; //semaphore operaion
  short int sem_flg //operation flag
 };
 
三、例子:
 2.1 服務器

#i nclude <sys/sem.h>
#i nclude <sys/ipc.h>

#define SEGSIZE 1024
#define READTIME 1
union semun {
 int val;
 struct semid_ds *buf;
 unsigned short *array;
} arg;
//生成信號量
int sem_creat(key_t key)
{
 union semun sem;
 int semid;
 sem.val = 0;
 semid = semget(key,1,IPC_CREAT|0666);
 if (-1 == semid){
  printf("create semaphore error/n");
  exit(-1);
 }
 semctl(semid,0,SETVAL,sem);
 return semid;
}
//刪除信號量
void del_sem(int semid)
{
 union semun sem;
 sem.val = 0;
 semctl(semid,0,IPC_RMID,sem);
}

//p
int p(int semid)
{
 struct sembuf sops={0,+1,IPC_NOWAIT};
 return (semop(semid,&sops,1));
}
//v
int v(int semid)
{
 struct sembuf sops={0,-1,IPC_NOWAIT};
 return (semop(semid,&sops,1));
}
int main()
{
 key_t key;
 int shmid,semid;
 char *shm;
 char msg[7] = "-data-";
 char i;
 struct semid_ds buf;
 
 key = ftok("/",0);
 shmid = shmget(key,SEGSIZE,IPC_CREAT|0604);
 if (-1 == shmid){
  printf(" create shared memory error/n");
  return -1;
 }
 shm = (char *)shmat(shmid,0,0);
 if (-1 == (int)shm){
  printf(" attach shared memory error/n");
  return -1;
 }
 semid = sem_creat(key);
 for (i = 0;i <= 3;i++){
  sleep(1);
  p(semid);
  sleep(READTIME);
  msg[5] = '0' + i;
  memcpy(shm,msg,sizeof(msg));
  sleep(58);
  v(semid);
 }
 shmdt(shm);
 shmctl(shmid,IPC_RMID,&buf);
 del_sem(semid);
 return 0;
//gcc -o shm shm.c -g
}
 
 2.2 客戶端
 
#i nclude <sys/sem.h>
#i nclude <time.h>
#i nclude <sys/ipc.h>

#define SEGSIZE 1024
#define READTIME 1
union semun {
 int val;
 struct semid_ds *buf;
 unsigned short *array;
} arg;

// 打印程序執行時間
void out_time(void)
{
 static long start = 0;
 time_t tm;
 if (0 == start){
  tm = time(NULL);
  start = (long)tm;
  printf(" now start .../n");
 }
 printf(" second: %ld /n",(long)(time(NULL)) - start);
}

//創建信號量
int new_sem(key_t key)
{
 union semun sem;
 int semid;
 sem.val = 0;
 semid = semget(key,0,0);
 if (-1 ==  semid){
  printf("create semaphore error/n");
  exit(-1);
 }
 return semid;
}

//等待信號量變成0
void wait_v(int semid)
{
 struct sembuf sops={0,0,0};
 semop(semid,&sops,1);
}

int main(void)
{
 key_t key;
 int shmid,semid;
 char *shm;
 char msg[100];
 char i;
 
 key = ftok("/",0);
 shmid = shmget(key,SEGSIZE,0);
 
 if(-1 == shmid){
  printf(" create shared memory error/n");
  return -1;
 }
 shm = (char *)shmat(shmid,0,0);
 if (-1 == (int)shm){
  printf(" attach shared memory error/n");
  return -1;
 }
 semid = new_sem(key);
 for (i = 0;i < 3;i ++){
  sleep(2);
  wait_v(semid);
  printf("Message geted is: %s /n",shm + 1);
  out_time();
 }
 shmdt(shm);
 return 0;
// gcc -o shmc shmC.c -g
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章