信号量/灯
1.概念
信号量代表某一类资源,其值标识系统中该资源的数量
信号量是一个受保护的变量,只能通过三种操作来访问
初始化
p操作(申请资源,资源-1)
v操作(释放资源,资源+1)
2.分类
3.无名信号量
信号量初始化
#include <semaphore.h>
int sem_init(sem_t *sem,int shared,unsigned int val)
sem:指向要初始化的信号量对象
shared指定为0,标识信号量只能由初始化这个信号量的进程使用,不能在进程间使用,linux不支持进程间同步
0:线程间
1:进程间
val:信号量初值
成功时返回0,失败时返回EOF
信号量P/V操作
#include <semaphore.h>
int sem_wait(sem_t *sem); //P操作
int sem_post(sem_t *sem); //V操作
sem指向要操作的信号量对象
成功时返回0,失败时返回EOF
销毁无名信号量
#include <semaphore.h>
int sem_destroy(sem_t *sem)
sem:信号量的地址
成功返回0失败返回-1
4.有名信号量
创建信号量
sem_t *sem_open(const char *name,int oflag,mode_t mode,unsigned int value)
name:有名信号量的名字,以"/"开头
oflag:标志位O_CREAT
mode:八进制权限 0777 0666
value:信号量初始化的值
信号量P/V操作
#include <semaphore.h>
int sem_wait(sem_t *sem); //P操作
int sem_post(sem_t *sem); //V操作
sem指向要操作的信号量对象
成功时返回0,失败时返回EOF
关闭信号量
#include <semaohore.h>
int sem_close(sem_t *sem);
sem:有名信号量的指针地址
成功返回0,失败返回-1
删除信号量
#include <semaphore.h>
int sem_unlink(const char *name)
name:有名信号量的名字
成功返回0,失败返回-1
5.有名信号和无名信号的区别
6.ipc信号灯
ftok函数创建key
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *path,int proj_id)
path:存在且可访问的文件的路径
proj_id:用于生成key的数字,范围1-255
成功时返回合法的key值,失败时返回EOF
创建信号灯集
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key,int nsems,int semflg)
key:和信号量关联的key
nsems:集合中包含的计数信号灯个数
semflg:标志位 IPC_CREAT|0666 IPC_EXCL
成功返回信号灯的id,失败返回-1
信号灯集初始化
#include <sys/ipc.h>
#include <sys/sem.h>
int semctl(int semid,int semnum,int cmd,...)
semid:要操作的信号量
semnum:要操作的集合中的信号灯编号
cmd:执行的操作 SETVAL IPC_RMID
union semun 取决于cmd
信号量pv操作
#include <sys/ipc.h>
#include <sys/sem.h>
int semop(int semid,struct sembuf* sops,unsigned nsops)
semid:要操作的信号量id
sops:描述对信号灯操作的结构体(数组)
nsops:要操作的信号灯的个数
struct sembuf
{
short sem_num;
short sem_op;
short sem_flg;
};
semnum 信号量编号
sem_op p操作 -1 v操作 1
sem_flg 0/IPC_NOWAIT
7.有名信号量测试
sem_w.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <fcntl.h> /* For O_* constants */
#include <sys/stat.h> /* For mode constants */
#include <semaphore.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
void delsemfile(int sig)
{
sem_unlink("sem_w");
exit(0);
}
int main()
{
key_t key;
int shmid;
char* addr;
sem_t *sem_w,*sem_r;
int ret;
struct sigaction act;
act.sa_handler = delsemfile;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction(SIGINT,&act,NULL);
key = ftok(".",10);
if(key < 0)
{
perror("ftok error\n");
return -1;
}
shmid = shmget(key,512,IPC_CREAT|0666);
if(shmid < 0)
{
perror("shmget error\n");
return -1;
}
addr = shmat(shmid,NULL,0);
if(addr == (void *)-1)
{
perror("shmat error\n");
}
sem_w = sem_open("sem_w",O_CREAT|O_RDWR,0666,1);
sem_r = sem_open ("sem_r",O_CREAT|O_RDWR,0666,0);
while(1)
{
sem_wait(sem_w);
printf(">>");
scanf("%s",addr);
sem_post(sem_r);
}
return 0;
}
sem_r.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
#include <signal.h>
#include <stdlib.h>
void delsemfile(int sig)
{
sem_unlink("sem_r");
exit(0);
}
int main()
{
key_t key;
int shmid;
char* addr;
sem_t *sem_w,*sem_r;
int ret;
struct sigaction act;
act.sa_handler = delsemfile;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction(SIGINT,&act,NULL);
key = ftok(".",10);
if(key < 0)
{
perror("ftok error\n");
return -1;
}
shmid = shmget(key,512,IPC_CREAT|0666);
if(shmid < 0)
{
perror("shmget error\n");
return -1;
}
addr = shmat(shmid,NULL,0);
if(addr == (void *)-1)
{
perror("shmat error\n");
}
sem_w = sem_open("sem_w",O_CREAT|O_RDWR,0666,1);
sem_r = sem_open ("sem_r",O_CREAT|O_RDWR,0666,0);
sem_wait(sem_r);
printf("%s\n",addr);
sem_post(sem_w);
return 0;
}
turn -1;
}
addr = shmat(shmid,NULL,0);
if(addr == (void *)-1)
{
perror(“shmat error\n”);
}
sem_w = sem_open(“sem_w”,O_CREAT|O_RDWR,0666,1);
sem_r = sem_open (“sem_r”,O_CREAT|O_RDWR,0666,0);
sem_wait(sem_r);
printf("%s\n",addr);
sem_post(sem_w);
return 0;
}