信号灯:多进程编程中需要关注进程间同步及互斥。同步是指多个进程为了完成同一个任务相互 协作运行,而互斥是指不同的进程为了争夺有限的系统资源(硬件或软件资源)而相互竞争 运行。
信号量是用来解决进程间的同步与互斥问题的一种进程间通信机制,它是一个特殊的变 量,变量的值代表着关联资源的可用数量。若等于 0 则意味着目前没有可用的资源。
信号量:
根据信号量的值可以将信号量分为二值信号量和计数信号量:
1、二值值信号量:信号量的值只有 0 和 1 值,若资源被锁住,信号量值为 0,若资源可 用则信号量值为 1;
2、计数信号量:信号量的值在 0 到一个大于 1 的值(最大 32767)。该计数表示可用 的资源的个数。 信号量只能进行的两个原子操作:P 操作:V 操作
1、 P 操作:如果有可用的资源(信号量值>0),则占用一个资源(给信号量值减 1); 如果没有可用的资源(信号量值=0),则进程被阻塞直到系统将资源分配给该进程 (进入信号量的等待队列,等到资源后唤醒该进程)。
2、V 操作:如果在该信号量的等待队列中有进程在等待资源,则唤醒一个阻塞进程; 如果没有进程等待它,则释放一个资源(给信号量值加 1)
定义信号变量; sem_t sem1 sem2
初始化信号量
P操作
V操作
信号灯:
信号灯集合(可以包含多个信号灯) IPC对象是一个信号灯集(多个信号量)
所有的函数是对一个集合的操作:
创建信号灯
int semget(key_t key, int nsems, int semflg);
`#include<sys/types.h>
#include<sys/sem.h>
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int main()
{
int semid;
semid =semget(IPC_PRIVATE,3, 0777);
if(semid <0)
{
printf("creat semaphore failure\n");
return -1;
}
printf("creat semaphore sucess semid = %d\n",semid);
system("ipcs -s");
while(1);
// msgctl(msgid,IPC_RMID,NULL);
// system("ipcs -q");
//system("ipcrm -m shmid");
return 0;
}`
删除信号灯
int semctl ( int semid, int semnum, int cmd,…union semun arg(不是地址));
#include<sys/types.h>
#include<sys/sem.h>
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int main()
{
int semid;
semid =semget(IPC_PRIVATE,3, 0777);
if(semid <0)
{
printf("creat semaphore failure\n");
return -1;
}
printf("creat semaphore sucess semid = %d\n",semid);
system("ipcs -s");
//删除信号灯
semctl(semid,0,IPC_RMID);
system("ipcs -s");
return 0;
}
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<semaphore.h>
sem_t sem;//初始化信号量
void *fun(void *var)
{
int j;
sem_wait(&sem);//运行到这里处于阻塞状态
for(j = 0;j < 10; j++)
{
usleep(10);
printf("this is fun j = %d\n",j);
}
}
int main()
{
int i;
char str[] = "hello linux\n";
pthread_t tid;
int ret;
sem_init(&sem,0,0);//信号量的初始化为0
ret = pthread_create(&tid,NULL,fun,(void *)str);
if(ret < 0)
{
printf("creat thread failure\n");
return -1;
}
for(i = 0; i < 10;i++)
{
usleep(100);
printf("this is main fun i = %d\n",i);
}
sem_post(&sem);//唤醒线程
while(1);
return 0;
}
这里要主要pthread的库在运行的时候 gcc smoop.c -ipthread
要加上连接的库的名称
(4)int semop ( int semid, struct sembuf *opsptr, size_t nops);
SETVAL:设置信号灯的值 信号灯的初始化,类似sem_init;
union semun
{
int val;
//SETVAL:设置信号灯的值
struct semid_ds *buf;
// IPC_STAT (获取对象属性)
//IPC_SET (设置对象属性)
unsigned short array; / Array for GETALL, SETALL */
struct seminfo __buf; / Buffer for IPC_INFO (Linux-specific) */
};
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<semaphore.h>
#include<sys/ipc.h>
#include<sys/sem.h>
//sem_t sem;//初始化信号量
int semid;
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *_buf;
};
union semun mysemun;
struct sembuf mysembuf;
void *fun(void *var)
{
int j;
//sem_wait(&sem);//运行到这里处于阻塞状态
mysembuf.sem_op = -1;
semop(semid,&mysembuf,1);
for(j = 0;j < 10; j++)
{
usleep(10);
printf("this is fun j = %d\n",j);
}
}
int main()
{
int i;
char str[] = "hello linux\n";
pthread_t tid;
int ret;
semid = semget(IPC_PRIVATE ,3,0777);
if(semid < 0)
{
printf("creat semaphore failure\n");
return -1;
}
printf("creat semaphore sucess,semid = %d\n",semid);
system("ipcs -s");
mysemun.val = 0;
semctl(semid, 0, SETVAL,mysemun);//信号量的初始化
mysembuf.sem_num = 0;
mysembuf.sem_flg = 0;
//sem_init(&sem,0,0);//信号量的初始化为0
ret = pthread_create(&tid,NULL,fun,(void *)str);
if(ret < 0)
{
printf("creat thread failure\n");
return -1;
}
for(i = 0; i < 10;i++)
{
usleep(100);
printf("this is main fun i = %d\n",i);
}
mysembuf.sem_op =1;
semop(semid,&mysembuf,1);
//sem_post(&sem);//唤醒线程
while(1);
return 0;
}
semctl不仅可以删除,还可以初始化信号量
通过信号量实现两个无亲缘关系的通信
服务器端
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<semaphore.h>
#include<sys/ipc.h>
#include<sys/sem.h>
//sem_t sem;//初始化信号量
int semid;
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *_buf;
};
union semun mysemun;
struct sembuf mysembuf;
int main()
{
int i;
pthread_t tid;
int key;
key = ftok("./a.c",'a');
if(key < 0)
{
printf("creat key failure\n");
return -1;
}
printf("creat key sucess\n");
semid = semget(key ,3,IPC_CREAT | 0777);
if(semid < 0)
{
printf("creat semaphore failure\n");
return -2;
}
printf("creat semaphore sucess,semid = %d\n",semid);
system("ipcs -s");
//mysemun.val = 0;
//semctl(semid, 0, SETVAL,mysemun);//信号量的初始化
mysembuf.sem_num = 0;
mysembuf.sem_flg = 0;
//sem_init(&sem,0,0);//信号量的初始化为0
for(i = 0; i < 10;i++)
{
usleep(100);
printf("this is main fun i = %d\n",i);
}
mysembuf.sem_op =1;
semop(semid,&mysembuf,1);
//sem_post(&sem);//唤醒线程
while(1);
return 0;
}
客户端
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<semaphore.h>
#include<sys/ipc.h>
#include<sys/sem.h>
//sem_t sem;//初始化信号量
int semid;
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *_buf;
};
union semun mysemun;
struct sembuf mysembuf;
int main()
{
int i;
pthread_t tid;
int key;
key = ftok("./a.c",'a');
if(key < 0)
{
printf("creat key failure\n");
return -1;
}
printf("creat key sucess\n");
semid = semget(key ,3,IPC_CREAT | 0777);
if(semid < 0)
{
printf("creat semaphore failure\n");
return -2;
}
printf("creat semaphore sucess,semid = %d\n",semid);
system("ipcs -s");
mysemun.val = 0;
semctl(semid, 0, SETVAL,mysemun);//信号量的初始化
mysembuf.sem_num = 0;
mysembuf.sem_flg = 0;
//sem_init(&sem,0,0);//信号量的初始化为0
mysembuf.sem_op = -1;
semop(semid,&mysembuf,1);
for(i = 0; i < 10;i++)
{
usleep(100);
printf("this is main fun i = %d\n",i);
}
//mysembuf.sem_op =1; P操作
//semop(semid,&mysembuf,1);
//sem_post(&sem);//唤醒线程
while(1);
return 0;
}
先运行客户端client代码,在运行服务端server代码,发现运行server代码后,客户端代码同步运行