天天看點

程序間通信之信号量(三)

信号量

信号量是記錄和統計臨界資源數目的計數器;

(一)建立信号量:

信号量的申請是以信号量集為機關的;

int semget(key_t key,int nsems,int semflag);

傳回值:信号量集的辨別符;

參數:

key:用key_t ftok(const char* pathname,int proj_id)來擷取;

nsems:表示要建立的這個信号量集中信号量的個數;

semflag:(1)IPC_CREAT:建立這個信号量集,若沒有就建立,若有則打開即可;

              (2)IPC_CREAT | IPC_EXCL:若建立的信号量不存在,則:建立;若建立的信号量存在,則:錯誤傳回;

(二)初始化信号量

int semctl(int semid,int semnum, int cmd,);

傳回值:(1)傳回值為0表示初始化成功;

             (2)初始化失敗,傳回-1;

參數:

semid:要初始化的信号量所在的信号量集的id;

semnum:要初始化的信号量是該信号量集的第幾個信号(從0開始);

cmd:設為SETVAL表示對信号量進行初始化;

(三)删除信号量

int semctl(int semid,int semnum,int cmd)

傳回值:(1)傳回值為0表示删除信号量成功;

              (2)傳回值為-1表示删除失敗;

參數:

semid:要删除的信号量集的id;

semnum:設定為0;

cmd:設定為IPC_RMID表示删除操作;

(四)P操作

int semop(int semid,struct sembuf*sops,unsigned nsops)

傳回值:(1)傳回值為0,表示操作成功;

              (2)傳回值為-1,表示操作成功;

參數:

semid:為操作的信号量所處的信号量集的id;

sops:所操作的信号量所在的數組;

struct sembuf

{

   unsigned short sem_num;  //操作信号量集中的哪一個信号量

   short sem_op;         //對于信号量執行什麼操作

   short sem_flg;

}

sops.sem_op = -1,位P操作;

nsops:操作的信号量的數目;

(五)V操作

int semop(int semid,struct sembuf*sops,unsigned nsops)

傳回值:(1)傳回值為0,表示操作成功;

              (2)傳回值為-1,表示操作失敗;

參數:semid:為操作的信号量所處的信号量集的id;

          sops:所操作的信号量所在的數組;

          sops.sem_op = 1,位V操作;

          nsops:操作的信号量的數目

common.h

#ifndef _COMMON_H_
#define _COMMON_H_

#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#define PATHNAME "/home/cm/code"
#define PROJ_ID 0x6666

union semun
{
    int val;
    struct semid_ds *buf;
    unsigned short *array;
    struct seminfo *_buf;
};

int Creat_Sem();
int Get_Sem();
int Init_Sem(int sem_id,int val);
int Destory_Sem(int sem_id);
int P(int sem_id,int who);
int V(int sem_id,int who);
#endif
           

common.c

#include"common.h"
static int CommonCreat_Sem(int flags)
{
    key_t key = ftok(PATHNAME,PROJ_ID);
    int sem_id =0;
    if(key<0)
    {
        perror("ftok");
        return -1;
    }
    else
    {
        sem_id = semget(key,1,flags);
        if(sem_id < 0)
        {
            perror("semget");
            return -2;
        }

    }
    return sem_id;
}
int Creat_Sem()
{
    int sem_id = CommonCreat_Sem(IPC_CREAT | IPC_EXCL | 0666);
    return sem_id;
}
int Get_Sem()
{
    int sem_id = CommonCreat_Sem(IPC_CREAT);
    return sem_id;
}

int Init_Sem(int sem_id,int Val)
{
    union semun _un;
    _un.val = Val;
    int ret = semctl(sem_id,0,SETVAL,_un);
    if(ret < 0)     //init failed
    {
        perror("semctl");
        return -1;
    }
    return 0;  //init success
}

int Destory_Sem(int sem_id)
{
    int ret = semctl(sem_id,0,IPC_RMID);
    if(ret < 0)
    {
        perror("semctl");
        return -1;
    }
    return 1;
}

static int CommonPV(int sem_id,int who,int op)
{
    struct sembuf _sf;
    _sf.sem_num = who;
    _sf.sem_op = op; //P:-1;V:1
    _sf.sem_flg = 0;
    int ret = semop(sem_id,&_sf,1);
    if(ret<0)
    {
        perror("semop");
        return -1;
    }
    return 0;
}
int P(int sem_id,int who)
{
    return CommonPV(sem_id,who,-1);
}

int V(int sem_id,int who)
{
    return CommonPV(sem_id,who,1);
}
           

Makefile

test:test_sem.c common.c
    gcc -o $@ $^

.PHONY:clean
clean:
    rm -f test
           

test_sem.c

#include"common.h"
int main()
{
	int sem_id = Creat_Sem();
	int val = 1;
	Init_Sem(sem_id,val);
	int pid = fork();
	if(pid == 0)
	{
	  //child
	  while(1)
	  {
		P(sem_id,0);
		printf("A");
		fflush(stdout);
		usleep(123456);
		printf("A");
		fflush(stdout);
		usleep(123456);
		V(sem_id,0);
	  }
	}
	else
	{
		while(1)
		{
		    P(sem_id,0);
			printf("B");
			fflush(stdout);
			usleep(123456);
			printf("B");
			fflush(stdout);
			V(sem_id,0);
		}
		wait(NULL);
	}
    printf("\n");
    Destory_Sem(sem_id);
    return 0;
}
           

注;

struct sembuf
{
   unsigned short sem_num;  //操作信号量集中的哪一個信号量
   short sem_op;         //對于信号量執行什麼操作
   short sem_flg;
}
           

sem_flg:

sem_flg是用來說明semop的操作方式;

(1)IPC_NOWAIT:對信号的操作不成功時,semop不會阻塞,并且立即傳回。 

(2)SEM_UNDO:程式結束的時候,對于資料進行復原,避免造成資料的二義性;

    對于二進制信号量來說,為了防止造成死鎖問題,必須在程式退出時,對于資料進行復原,防止造成二義性;産生結果的不确定性;

作者水準有限,若有問題,請留言,謝謝!!!

繼續閱讀