进程间利用信号量进行独占式访问

semun:   一般为NULL             //要定义一个union信号量集
        union semun{
            int val;               //SETVAL的值
            struct semid_ds *buf;  //buffer for IPC_STAT & IPC_SET
            unsigned short *array; //array for GETALL&SETALL

        }     

int semget(key_t key, int num_sems, int sem_flags);  //创建一个信号量/取得一个已有信号量的键值  输出为信号量标识符
    key: 信号量键值;信号量提供一个键值,通过semget()生成一个信号量标识符,其他信号量函数只能用semget()返回的信号量标识符来操作信号量  
         特殊信号量键值:IPC_PRIVATE,作用是:只有创建者进程才可以访问该信号量
    num_sems: 信号量数目,几乎都是 1
    sem_flags: 0666 | IPC_CREAT, 0666为文件的访问权限,与IPC_CREAT结合,限定生成的信号量是一个新的信号量,若再加一个IPC_EXCL,表示生成一个新的、唯一的信号量

int semop(int sem_id, struct sembuf *sem_ops, size_t num_sem_ops);  //改变信号量的值
    sem_id: 信号量标识符 由semget()生成
    sem_ops:
            struct sembuf{
                short sem_num;  //一般为0,除非你要用一组信号量,否则就是一个信号量,值为0
                short sem_op;   //1, 对信号量进行±的间隔值,这里取1,表示要么+1,要么-1
                short sem_flag; //一般为SEM_UNDO,让操作系统在进程 没有释放该信号量的情况下,去释放这个信号量, 确保释放掉
            }
    num_sem_ops: 具体执行几次P/V操作

int semctl(int sem_id, int sem_num, int command, (union semun));  //直接控制信号量信息
    sem_id: 信号量标识符
    sem_num: 一般为0,除非你要用一组信号量,否则就是一个信号量,值为0
    command: SETBAL/IPC_RMID  信号量初始化/删除信号量    
    semun:   一般为NULL
            union semun{
                int val;               //SETVAL的值
                struct semid_ds *buf;  //buffer for IPC_STAT & IPC_SET
                unsigned short *array; //array for GETALL&SETALL

            }

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

#include <sys/sem.h>//包含信号量定义的头文件

//联合类型semun定义
union semun{
	int val;
	struct semid_ds *buf;
	unsigned short *array;
};

//函数声明
//函数:设置信号量的值
static int set_semvalue(void);
//函数:删除信号量
static void del_semvalue(void);
//函数:信号量P操作
static int semaphore_p(void);
//函数:信号量V操作
static int semaphore_v(void);

static int sem_id;//信号量ID


int main(int argc,char *argv[])
{
	int i;
	int pause_time;
	char op_char = 'O';

	srand((unsigned int)getpid());

	//创建一个新的信号量或者是取得一个已有信号量的键
	sem_id = semget((key_t)1234,1,0666 | IPC_CREAT);

	//如果参数数量大于1,则这个程序负责创建信号和删除信号量
	if(argc > 1)
	{
	    if(!set_semvalue())
	    {
	    	fprintf(stderr,"failed to initialize semaphore\n");
		exit(EXIT_FAILURE);
	    }

	    op_char = 'X';//对进程进行标记
	    sleep(5);
	}

	//循环:访问临界区
	for(i = 0;i < 10;++i)
	{
	    //P操作,尝试进入缓冲区
	    if(!semaphore_p())
		exit(EXIT_FAILURE);
	    printf("%c",op_char);
	    fflush(stdout);
            //刷新标准输出缓冲区,把输出缓冲区里的东西打印到标准输出设备上

	    pause_time = rand() % 3;
	    sleep(pause_time);

	    printf("%c",op_char);
	    fflush(stdout);

	    //V操作,尝试离开缓冲区
	    if(!semaphore_v())
		exit(EXIT_FAILURE);
	    pause_time = rand() % 2;
	    sleep(pause_time);
	}

	printf("\n %d - finished \n",getpid());

	if(argc > 1)
	{
		sleep(10);
		del_semvalue();//删除信号量
	}
}


//函数:设置信号量的值
static int set_semvalue(void)
{
	union semun sem_union;
	sem_union.val = 1;

	if(semctl(sem_id,0,SETVAL,sem_union))
	    return 0;

	return 1;
}

//函数:删除信号量
static void del_semvalue(void)
{
	union semun sem_union;

	if(semctl(sem_id,0,IPC_RMID,sem_union))
		fprintf(stderr,"Failed to delete semaphore\n");
}

//函数:信号量P操作:对信号量进行减一操作
static int semaphore_p(void)
{
	struct sembuf sem_b;

	sem_b.sem_num = 0;//信号量编号
	sem_b.sem_op = -1;//P操作
	sem_b.sem_flg = SEM_UNDO;

	if(semop(sem_id,&sem_b,1) == -1)
	{
	    fprintf(stderr,"semaphore_p failed\n");
	    return 0;
	}

	return 1;
}

//函数:信号量V操作:对信号量进行加一操作
static int semaphore_v(void)
{
	struct sembuf sem_b;

	sem_b.sem_num = 0;//信号量编号
	sem_b.sem_op = 1;//V操作
	sem_b.sem_flg = SEM_UNDO;

	if(semop(sem_id,&sem_b,1) == -1)
	{
	    fprintf(stderr,"semaphore_v failed\n");
	    return 0;
	}

	return 1;

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值