#include
int semget(key_t key, int nsems, int semflg);
功能:创建一个新的旗语或取得一个已有的旗语。
返回值:成功返回旗语标识符,失败返回-1。
参数:
key:系统范围内的唯一标识符,其它进程访问旗语的依据。IPC_PRIVATE告诉semget自己生成标识符,所以其它进程无法访问该旗语。使用ftok()函数获得唯一标识。
nsems:旗语个数,为1时表示单个旗语,大于1表示旗语数组,用来获取已有旗语时设为0
semflg:指令和访问权限标志,
IPC_CREAT创建新的旗语,IPC_CREAT|IPC_EXCL如果旗语存在则失败,errno设为EEXIST。semflg=0用来获取一个已有的旗语。打开权限类似open(),相当于文件的访问权限。
- /*
- * 创建信号量
- * Lzy 2011-6-16
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- int main(void)
- {
- int semid;
- key_t key;
- key = ftok("main.c", '1'); //获取键值
- if(key < 0)
- {
- perror("ftok");
- exit(0);
- }
- semid = semget(key, 1, IPC_CREAT | 0666); //创建一个信号量
- if(semid < 0)
- {
- perror("semget");
- exit(0);
- }
- printf("Done\n");
- return 0;
- }
#include
int semop(int semid, struct sembuf *sops, size_t nsops);
功能:提供获取和释放旗语或旗语数组的方法。
返回值:成功返回0,否则-1。
参数:
semid:旗语描述符。
sops:旗语结构(数组)指针,包含了具体操作。
struct sembuf{
unsigned short sem_num; //对应旗语数组中的旗语,0对应第一个旗语
short sem_op; //旗语的当前值记录相应资源目前可用数目;sem_op>0进程要释放sem_op数目的共享资源;sem_op=0用于对共享资源是否已用完的测试(调用进程将调用sleep(),直到信号量的值为0);sem_op<0进程要申请-sem_op个共享资源
short sem_flg; //IPC_NOWAIT:无旗语可用则失败,SEM_UNDO:在进程结束时,相应的操作将被取消,如果设置了该标志位,在进程没有释放共享资源就退出时,内核将代为释放。
};
nsops要进行旗语操作的数量(旗语结构(数组)元素个数)。
#include
int semctl(int semid, int semnum, int cmd, …);
功能:控制旗语信息。
返回值:成功返回0(或要获取的值),否则-1。
参数:
semid:旗语标识符。
semnum:旗语编号。
cmd:要进行的操作。
第四个参数,是union semun的实例,具体值依赖cmd。
union semun{
int val;
struct semid_ds *buf;
unsigned short *array;
}arg;
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <error.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- #include <sys/wait.h>
- int main()
- {
- int semid;
- pid_t pid;
- key_t key;
- struct sembuf lock = {0, -1, SEM_UNDO};
- struct sembuf unlock = {0, 1, SEM_UNDO | IPC_NOWAIT};
- int i, ret, status;
- key = ftok("/home/yanyb", 'b'); /* 生成信号量的键值 */
- semid = semget(key, 1, IPC_CREAT | 0666); /* 创建一个信号量集 */
- if(semid < 0) /* 如果信号量创建失败,输出错误信息并退出 */
- {
- perror("semget error");
- exit(1) ;
- }
- ret = semctl(semid, 0, SETVAL, 1); /* 将信号量的值设为1 */
- if(ret == -1) /* 如果操作失败,输出错误信息并退出 */
- {
- perror("semctl error");
- exit(1);
- }
- pid = fork(); /* 创建子进程 */
- if(pid < 0) /* 如果进程创建失败,输出错误信息并退出 */
- {
- printf("fork error");
- exit(1);
- }
- if(pid == 0) /* 子进程 */
- {
- for(i=0; i<3; i++)
- {
- sleep(abs((int)(3.0*rand()/(RAND_MAX+1)))); /* 休眠0~3秒 */
- ret = semop(semid, &lock, 1); /* 申请访问共享资源 */
- if(ret == -1)
- {
- perror("lock error");
- exit(1);
- }
- printf("Child process access the resource.\n"); /* 开始访问共享资源 */
- sleep(abs((int)(3.0*rand()/(RAND_MAX+1))));
- printf("Complete!\n");
- ret = semop(semid, &unlock, 1); /* 共享资源访问完毕 */
- if(ret == -1)
- {
- perror("unlock error");
- exit(1);
- }
- }
- }
- else /* 父进程 */
- {
- for(i=0; i<3 ;i++)
- {
- sleep(abs((int)(3.0*rand()/(RAND_MAX+1))));
- ret = semop(semid, &lock, 1); /* 申请访问共享资源 */
- if(ret == -1)
- {
- perror("lock error");
- exit(1);
- }
- printf("Parent process access the resource.\n"); /* 开始访问共享资源 */
- sleep(abs((int)(3.0*rand()/(RAND_MAX+1))));
- printf("Complete!\n");
- ret = semop(semid, &unlock, 1); /* 共享资源访问完毕 */
- if(ret == -1)
- {
- perror("unlock error");
- exit(1);
- }
- }
- if(pid != wait(&status)) /* 等待子进程结束 */
- {
- printf("wait error");
- exit(1);
- }
- ret = semctl(semid, 0, IPC_RMID, 0); /* 删除信号量 */
- if(ret == -1) /* 如果信号量删除失败,输出错误信息并退出 */
- {
- perror("semctl error");
- exit(1);
- }
- }
- return 0;
- }
阅读(1601) | 评论(0) | 转发(2) |