(我记得好像也是友善的代码~~~~好像是,好像也不是~~~~)
Linux信号量简介
1:信号量
信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用。在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量。
信号量类似于线程一章中使用的互斥锁,但更强大,信号量可以在数个(大于两个)线程中使用,而且可以使用信号集管理大量的信号量。同样,信号量也有有名信号量和无名信号量。
信号量的使用主要是用来保护共享资源,使得资源在一个时刻只有一个进程(线程)所拥有。
信号量的值为正的时候,说明它空闲。所测试的线程可以锁定而使用它。若为0,说明它被占用,测试的线程要进入睡眠队列中,等待被唤醒。
2:简单的信号量程序
程序简述:
程序描述了最简单的无名信号量的用法,类似与互斥锁。至于有名信号量在初始化部分有所不同,而且在结束时需要释放。下面提供的三个程序,第一个为无名信号量在线程程间的应用,其余两个为有名信号量在两个进程间的应用。
重点掌握函数:
pthread_join()
sem_init()
sem_wait()
sem_post()
sem_open()
Shmat()
sem_close()
sem_unlink()
shmctl()
程序代码:
#include <pthread.h>
//信号集所在库
#include <sys/sem.h>
//信号量所在库
#include <semaphore.h>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
//编译时需要添加库 gcc -pthread -o outfile.out filename.c
int number; // 被保护的全局变量
sem_t sem_id1, sem_id2; //信号量!!若在进程中只需要定义一个,因为系统 //会复制一份出来
void* thread_one_fun(void *arg)
{
sem_wait(&sem_id1); //如果信号量不为0则减一
printf("thread_one have the semaphore\n");
number++;
printf("number = %d\n",number); //输出加一后的值
sem_post(&sem_id2); //信号量加一
}
void* thread_two_fun(void *arg)
{
sem_wait(&sem_id2); //如果信号量不为0则减一
printf("thread_two have the semaphore \n");
number--;
printf("number = %d\n",number); //输出减一后的值
sem_post(&sem_id1); //信号量加一
}
int main(int argc,char *argv[])
{
number = 1;
pthread_t id1, id2;
sem_init(&sem_id1, 0, 1); // 信号空闲的
sem_init(&sem_id2, 0, 0); // 信号忙的
pthread_create(&id1,NULL,thread_one_fun, NULL);//建立线程1
pthread_create(&id2,NULL,thread_two_fun, NULL);//建立线程2
pthread_join(id1,NULL); //等待线程1结束
pthread_join(id2,NULL); //等待线程2结束
printf("this is main\n");
return 0; //程序结束返回正常标志
}
有名信号量在两个进程间使用,有名信号量使用了两个c文件生成两个进程,通过信号量管理共享内存归谁调用:
//Server.c内容:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define SHMSZ 27
char SEM_NAME[]= "vik";
int main()
{
char ch;
int shmid;
key_t key;
char *shm,*s;
sem_t *mutex; //信号量
//name the shared memory segment
key = 1000; //有名信号的内存段
//create & initialize semaphore
mutex = sem_open(SEM_NAME,O_CREAT,0644,1);//创建和初始化信号量
if(mutex == SEM_FAILED) //如果创建失败则
{
perror("unable to create semaphore");
sem_unlink(SEM_NAME); //删除信号量并退出
exit(-1);
}
//create the shared memory segment with this key
shmid = shmget(key,SHMSZ,IPC_CREAT|0666);//创建共享内存段的关键
if(shmid<0) //如果失败则输出错误
{ //并且退出
perror("failure in shmget");
exit(-1);
}
//attach this segment to virtual memory
shm = shmat(shmid,NULL,0); //将这段共享内存虚拟化
//start writing into memory
s = shm; //记录这段虚拟内存
for(ch='A';ch<='Z';ch++)
{
sem_wait(mutex); //信号量自减等待客户端的信号量增加
*s++ = ch; //在共享内存地址上写入字符
sem_post(mutex); //信号量自加释放信号量
}
//the below loop could be replaced by binary semaphore
while(*shm != '*')
{
sleep(1);
}
sem_close(mutex); //关闭信号量,信号量被清0
sem_unlink(SEM_NAME); //正常释放信号量,若不为0则等其为 //0
shmctl(shmid, IPC_RMID, 0); //关闭共享内存
exit(0); //退出
}
///
//Client.c内容
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define SHMSZ 27
char SEM_NAME[]= "vik";
int main()
{
char ch;
int shmid;
key_t key;
char *shm,*s;
sem_t *mutex;
//name the shared memory segment
key = 1000;
//create & initialize existing semaphore
mutex = sem_open(SEM_NAME,0,0644,0); //打开已存在的信号量
if(mutex == SEM_FAILED)
{
perror("reader:unable to execute semaphore");
sem_close(mutex);
exit(-1);
}
//create the shared memory segment with this key
shmid = shmget(key,SHMSZ,0666); //打开共享内存
if(shmid<0)
{
perror("reader:failure in shmget");
exit(-1);
}
//attach this segment to virtual memory
shm = shmat(shmid,NULL,0); //虚拟共享内存
//start reading
s = shm;
for(s=shm;*s!=NULL;s++)
{
sem_wait(mutex); //等待其他进程释放信号
putchar(*s); //输出共享内存中的字符
sem_post(mutex); //释放信号
}
//once done signal exiting of reader:This can be replaced by another semaphore
*shm = '*'; //关闭信号量和共享内存
sem_close(mutex);
shmctl(shmid, IPC_RMID, 0);
exit(0);
}