(简单了解信号量函数(semget、semop、semctl)及其范例:https://blog.csdn.net/guoping16/article/details/6584043)
1、掌握Linux下线程的概念;
2、了解Linux线程同步与通信的主要机制;
3、通过信号灯操作实现线程间的同步与互斥。
通过Linux多线程与信号灯机制,设计并实现计算机线程与I/O线程共享缓冲区的同步与通信。
程序要求:两个线程,共享公共变量a
线程1负责计算(1到100的累加,每次加一个数)
线程2负责打印(输出累加的中间结果)
#include
#include
#include
#include
#include
union semun {
int val; /* value for SETVAL */
struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* array for GETALL, SETALL */
struct seminfo *__buf; /* buffer for IPC_INFO */
};
int i=0,sum=0;
int semid;//信号量集合首地址
pthread_t p1,p2;
union semun arg;
void P(int semid, int index);
void V(int semid, int index);
/***对信号量数组index编号的信号量做P操作***/
void P(int semid, int index){
struct sembuf sem={index,-1,0};
semop(semid,&sem,1);
}
/***对信号量数组index编号的信号量做V操作***/
void V(int semid, int index){
struct sembuf sem={index,+1,0};
semop(semid,&sem,1);
}
/*线程一*/
void thread_1(void){
for(;i<=100;i++){
P(semid,0);
printf("This is a pthread_1.\ni=%d\n",i);
sum+=i;
V(semid,1);
}
return;
}
/*线程二*/
void thread_2(void){
for(;;){
P(semid,1);
printf("This is a pthread_2.\nsum=%d\n",sum);
if(i==101)return;
V(semid,0);
}
}
int main(){
int key ;
int ret;
key=ftok("/tmp", 0x66 ) ;
if(key<0){
perror("ftok key error") ;
return -1 ;
}
/***创建两个信号量***/
semid=semget(key,2,IPC_CREAT|0666);
if(semid==-1){
perror("create semget error");
return ;
}
/***对0号信号量设置初始值***/
arg.val=1;
ret=semctl(semid,0,SETVAL,arg);//信号量semid【0】为1
arg.val=0;
ret =semctl(semid,1,SETVAL,arg);//信号量semid【1】为0
if (ret < 0 ){
perror("ctl sem error");
semctl(semid,0,IPC_RMID,arg);
return -1 ;
}
/*创建线程一*/
ret=pthread_create(&p1,NULL,(void *) thread_1,NULL);
if(ret!=0) {
printf("Create pthread error!\n");
return -1;
}
/*创建线程二*/
ret=pthread_create(&p2,NULL,(void *) thread_2,NULL);
if(ret!=0) {
printf("Create pthread error!\n");
return -1;
}
/*等待线程结束*/
pthread_join(p1,NULL);
pthread_join(p2,NULL);
/***删除信号量***/
semctl(semid,0,IPC_RMID,arg);
semctl(semid,1,IPC_RMID,arg);
return 0;
}
运行结果: