semctl(semid, 0, SETVAL, sem_union)
时间: 2023-10-04 15:11:38 浏览: 52
这段代码是用来设置信号量集中第一个信号量的值的。其中,semid是信号量集的标识符,0表示要设置的信号量的下标,SETVAL表示要设置的操作是设置信号量的值,sem_union是一个联合体类型的变量,用来指定要设置的信号量的初始值。
举个例子,如果我们要创建一个包含3个信号量的信号量集,然后将第一个信号量的值设置为1,可以这样写:
```
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
};
int semid = semget(IPC_PRIVATE, 3, IPC_CREAT | 0666);
union semun sem_union;
sem_union.val = 1;
semctl(semid, 0, SETVAL, sem_union);
```
这样就创建了一个包含3个信号量的信号量集,第一个信号量的值为1。
相关问题
#include<stdio.h> #include<stdlib.h> #include<sys/ipc.h> #include<sys/shm.h> #include<sys/sem.h> #include<string.h> typedef struct _test{ int a_val; int b_val; int a_flag; int b_flag; int game_no; int stage; }test; int pk[3][3] = {0,-1,1,1,0,-1,-1,1,0}; void sem_p(); void sem_v(); void set_sem(); void del_sem(); int sem_id; union semun{ int val; struct semid_ds *buf; unsigned short *arry; }; int main(){ int shmid; test* shm; shmid = shmget((key_t)1236,sizeof(test),0666|IPC_CREAT); if(shmid == -1){ printf("shmget failed\n"); exit(EXIT_FAILURE); } printf("%d",shmid); shm = shmat(shmid,0,0); if (shm == (void*)-1){ printf("shmat failed\n"); exit(EXIT_FAILURE); } printf("\nMemory attached at %X\n",(int)shm); sem_id = semget((key_t)3000,1,0666|IPC_CREAT); set_sem(); int no=0,debug=0,a,b; shm->a_flag=0; shm->a_val = -2; shm->b_flag=0; shm->b_val = -2; shm->game_no=1; shm->stage=0; while(1){ sem_p(); //printf("a:%d b:%d\n",shm->a_val,shm->b_val); sleep(1); if(shm->game_no==-1){ sem_v(); break; } if (shm->stage==0){ if(no!=shm->game_no){ no = shm->game_no; printf("-------------------\n"); printf("game_no:%d\n",no); } if(shm->a_flag==1 && shm->b_flag==1) shm->stage=1; } else if(shm->stage==1){ printf("a:%d\n",shm->a_val); printf("b:%d\n",shm->b_val); a = pk[shm->a_val][shm->b_val]; b = pk[shm->b_val][shm->a_val]; shm->a_val=a; shm->b_val=b; shm->a_flag=0; shm->b_flag=0; shm->stage=2; } else if(shm->stage==2){ if(shm->a_flag==1 && shm->b_flag==1){ shm->stage=0; shm->game_no++; shm->a_flag=0; shm->b_flag=0; printf("-------------------\n"); if(shm->game_no > 100) shm->game_no=-1; } } sem_v(); } shmdt(shm); int ret=0; ret = shmctl(shmid,IPC_RMID,NULL); if(ret<0){ printf("shmctl error!\n"); } del_sem(); printf("finish"); } void set_sem(){ union semun sem_union; sem_union.val=1; semctl(sem_id,0,SETVAL,sem_union); } void del_sem(){ union semun sem_union; semctl(sem_id,0,IPC_RMID,sem_union); } void sem_p(){ struct sembuf sem_b; sem_b.sem_num = 0; sem_b.sem_op = -1; sem_b.sem_flg = SEM_UNDO; semop(sem_id,&sem_b,1); } void sem_v(){ struct sembuf sem_b; sem_b.sem_num = 0; sem_b.sem_op = 1; sem_b.sem_flg = SEM_UNDO; semop(sem_id,&sem_b,1); }
这段代码是一个使用共享内存和信号量实现的石头剪刀布游戏程序。程序中创建了一个共享内存区域,用于存储游戏的状态和玩家的选择结果。同时,使用了一个信号量来控制共享内存的访问,防止多个进程同时修改共享内存的内容。
具体来说,程序中定义了一个结构体test,用于存储游戏的状态和玩家的选择结果。其中包括两个整型变量a_val和b_val,分别表示玩家A和玩家B的选择,-2表示未做出选择;a_flag和b_flag,表示玩家A和玩家B是否已经做出选择,0表示未做出选择,1表示已做出选择;game_no,表示当前游戏的轮数;stage,表示游戏的阶段,0表示等待玩家做出选择,1表示计算结果,2表示等待下一轮游戏开始。
在主函数中,程序首先创建了一个共享内存区域,然后使用shmat函数将共享内存映射到本进程的地址空间中。接着,创建了一个信号量,用于控制共享内存的访问。程序采用了PV操作,即sem_p和sem_v函数,来实现对信号量的操作。
程序进入死循环,在循环中不断检查共享内存的状态。如果游戏轮数已经超过100轮,则结束游戏,否则等待玩家做出选择。如果两个玩家都已经做出选择,则计算结果,并等待下一轮游戏开始。
最后,使用shmdt函数将共享内存从本进程的地址空间中分离,使用shmctl函数删除共享内存区域,使用del_sem函数删除信号量。
河的南边和河的北边的中间有一座小桥,小桥中间宽两边窄,中间每次最多允许两人通过,两边每次最多允许一人通过,使用PV信号量实现过此桥的程序。请给出在linux下运行的完整的c++代码。
好的,这是一份使用PV信号量实现桥的过河问题的C代码,可以在Linux下运行:
```
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sem.h>
#define BRIDGE_KEY 1234
#define MAX_PEOPLE 3
#define MAX_WALKERS 2
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
};
void bridge_cross(int direction, int *bridge_sem_id, int *north_sem_id, int *south_sem_id) {
struct sembuf bridge_wait[2], bridge_cross[2], bridge_post[2];
int bridge_wait_count = 2, bridge_cross_count = 2, bridge_post_count = 2;
if (direction == 0) {
bridge_wait[0].sem_num = 0;
bridge_wait[0].sem_op = -1;
bridge_wait[0].sem_flg = SEM_UNDO;
bridge_cross[0].sem_num = 1;
bridge_cross[0].sem_op = -1;
bridge_cross[0].sem_flg = SEM_UNDO;
bridge_post[0].sem_num = 2;
bridge_post[0].sem_op = 1;
bridge_post[0].sem_flg = SEM_UNDO;
bridge_wait[1].sem_num = 3;
bridge_wait[1].sem_op = -1;
bridge_wait[1].sem_flg = SEM_UNDO;
bridge_cross[1].sem_num = 0;
bridge_cross[1].sem_op = -1;
bridge_cross[1].sem_flg = SEM_UNDO;
bridge_post[1].sem_num = 1;
bridge_post[1].sem_op = 1;
bridge_post[1].sem_flg = SEM_UNDO;
} else {
bridge_wait[0].sem_num = 3;
bridge_wait[0].sem_op = -1;
bridge_wait[0].sem_flg = SEM_UNDO;
bridge_cross[0].sem_num = 2;
bridge_cross[0].sem_op = -1;
bridge_cross[0].sem_flg = SEM_UNDO;
bridge_post[0].sem_num = 1;
bridge_post[0].sem_op = 1;
bridge_post[0].sem_flg = SEM_UNDO;
bridge_wait[1].sem_num = 0;
bridge_wait[1].sem_op = -1;
bridge_wait[1].sem_flg = SEM_UNDO;
bridge_cross[1].sem_num = 3;
bridge_cross[1].sem_op = -1;
bridge_cross[1].sem_flg = SEM_UNDO;
bridge_post[1].sem_num = 2;
bridge_post[1].sem_op = 1;
bridge_post[1].sem_flg = SEM_UNDO;
}
semop(*bridge_sem_id, bridge_wait, bridge_wait_count);
printf("Person %d is crossing the bridge.\n", getpid());
sleep(1);
semop(*bridge_sem_id, bridge_cross, bridge_cross_count);
printf("Person %d has crossed the bridge.\n", getpid());
semop(*bridge_sem_id, bridge_post, bridge_post_count);
if (direction == 0) {
sem_post(north_sem_id);
} else {
sem_post(south_sem_id);
}
exit(EXIT_SUCCESS);
}
int main(int argc, char *argv[]) {
int north_sem_id, south_sem_id, bridge_sem_id, i;
union semun north_sem_union, south_sem_union, bridge_sem_union;
north_sem_id = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT);
south_sem_id = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT);
bridge_sem_id = semget(BRIDGE_KEY, 1, 0666 | IPC_CREAT);
north_sem_union.val = MAX_PEOPLE;
south_sem_union.val = MAX_PEOPLE;
bridge_sem_union.val = MAX_WALKERS;
semctl(north_sem_id, 0, SETVAL, north_sem_union);
semctl(south_sem_id, 0, SETVAL, south_sem_union);
semctl(bridge_sem_id, 0, SETVAL, bridge_sem_union);
for (i = 0; i < 6; i++) {
if (fork() == 0) {
if (i % 2 == 0) {
sem_wait(&north_sem_id);
bridge_cross(0, &bridge_sem_id, &north_sem_id, &south_sem_id);
} else {
sem_wait(&south_sem_id);
bridge_cross(1, &bridge_sem_id, &north_sem_id, &south_sem_id);
}
}
}
for (i = 0; i < 6; i++) {
wait(NULL);
}
semctl(north_sem_id, 0, IPC_RMID);
semctl(south_sem_id, 0, IPC_RMID);
semctl(bridge_sem_id, 0, IPC_RMID);
return 0;
}
```
这个程序使用了3个不同的信号量:一个用于北岸等待的人,一个用于南岸等待的人,以及一个用于桥上行走的人数。每个人都是使用 fork() 创建的子进程,如果进程编号是偶数,它会等待北岸信号量,否则它会等待南岸信号量。
一旦一个人获得了它等待的信号量,它就调用 bridge_cross() 函数,该函数使用 semop() 操作等待桥上空闲的信号量,然后将桥上人数增加1,最后释放等待的信号量。然后,该进程会在桥上等待1秒钟,然后再次使用 semop() 操作等待桥上空闲的信号量,然后将桥上人数减少1,最后释放等待的信号量。
最后,主进程会等待所有子进程结束并删除创建的信号量。