一、信号量
信号量一般的作用就是用在进程之间的互斥和同步操作,跟线程的锁机制差不多的作用。线程当然也可以使用信号量来进行互斥、同步。
二、程序示例
/*commom.h*/
#ifndef _COMMOM_H_
#define _COMMOM_H_
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h>
#include <unistd.h>
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
};
int init_sem(int semid)
{
union semun sem;
sem.val = 1;
if (semctl(semid, 0, SETVAL, sem)==-1)
{
printf("set_sem failed!\n");
exit(1);
}
return 0;
}
int del_sem(int semid)
{
union semun sem;
if (semctl(semid, 0, IPC_RMID, sem)==-1)
{
printf("del_sem failed!\n");
exit(1);
}
return 0;
}
int create_sem(key_t key, int num_sems)
{
int semid;
semid = semget(key, num_sems, 0666|IPC_CREAT);
if (semid == -1)
{
printf("create_sem failed!\n");
exit(1);
}
return semid;
}
int sem_p(int semid)
{
struct sembuf sem_buf;
sem_buf.sem_num = 0;
sem_buf.sem_op = -1;
sem_buf.sem_flg = SEM_UNDO;
if (semop(semid, &sem_buf, 1)==-1)
{
printf("sem_p failed!\n");
exit(1);
}
return 0;
}
int sem_v(int semid)
{
struct sembuf sem_buf;
sem_buf.sem_num = 0;
sem_buf.sem_op = +1;
sem_buf.sem_flg = SEM_UNDO;
if (semop(semid, &sem_buf, 1)==-1)
{
printf("sem_p failed!\n");
exit(1);
}
return 0;
}
#endif
/*sem_write1.c*/
#include <stdio.h>
#include <stdlib.h>
#include "commom.h"
int main(void)
{
FILE *fp;
key_t key;
int semid;
key = ftok("./commom.h", 0);
printf("0x%x\n", key);
semid = create_sem(key, 1);
fp = fopen("./text.txt", "a+");
sem_p(semid);
fwrite("english\n", 8, 1, fp);
sem_v(semid);
sleep(5);
sem_p(semid);
fwrite("test\n", 5, 1, fp);
sem_v(semid);
sleep(5);
fclose(fp);
del_sem(semid);
return 0;
}
/*sem_write2.c*/
#include <stdio.h>
#include <stdlib.h>
#include "commom.h"
int main(void)
{
int semid;
key_t key;
FILE *fp;
fp = fopen("./text.txt", "a+");
key = ftok("./commom.h", 0);
printf("0x%x\n", key);
semid = create_sem(key, 1);
init_sem(semid);
sem_p(semid);
fwrite("hello\n", 6, 1, fp);
sem_v(semid);
sleep(5);
sem_p(semid);
fwrite("world\n", 6, 1, fp);
sem_v(semid);
fclose(fp);
return 0;
}
#makefile
CFLAGS = -Wall -g
CC = gcc
TARGET = sem_write1 sem_write2
all:$(TARGET)
sem_write1:sem_write1.o
$(CC) $(CFLAGS) -o $@ $^
sem_write2:sem_write2.o
$(CC) $(CFLAGS) -o $@ $^
%.o:%.c %.h
$(CC) -c -o $@ $<
clean:
rm -f $(TARGET) *.o
注意:先运行sem_write2,因为sem_write2有对信号量进行初始化的操作,然后才能进行P/V操作。