信号量

/*
 * semgTest.cpp
 *
 *  Created on: Jun 27, 2013
 *      Author: zsf
 */
#include "semgTest.h"

//联合类型semun定义
union semun {
        int val;
        struct semid_ds *buf;
        unsigned short *array;
};

//函数声明
//函数:设置信号量的值
static int set_semvalue(void);
//函数:删除信号量
static void del_semvalue(void);
//函数:信号量P操作
static int semaphore_p(void);
//函数:信号量V操作
static int semaphore_v(void);

static int sem_id;//信号量ID


int main(int argc, char *argv[]) {
    int i;
    int pause_time;
    char op_char = 'O';

    srand((unsigned int) getpid());


    //创建一个新的信号量或者是取得一个已有信号量的键
    sem_id = semget((key_t) 1234, 1, 0666 | IPC_CREAT);


    //如果参数数量大于1,则这个程序负责创建信号和删除信号量
    if (argc > 1) {
        if (!set_semvalue()) {
            fprintf(stderr, "failed to initialize semaphore\n");
            exit(EXIT_FAILURE);
        }

        op_char = 'X';//对进程进行标记
        sleep(5);
    }

    //循环:访问临界区
    for (i = 0; i < 10; ++i) {
        //P操作,尝试进入缓冲区
        if (!semaphore_p())
            exit(EXIT_FAILURE);
        printf("%c", op_char);
        fflush(stdout);//刷新标准输出缓冲区,把输出缓冲区里的东西打印到标准输出设备上

        pause_time = rand() % 3;
        sleep(pause_time);

        printf("%c", op_char);
        fflush(stdout);


        //V操作,尝试离开缓冲区
        if (!semaphore_v())
            exit(EXIT_FAILURE);
        pause_time = rand() % 2;
        sleep(pause_time);
    }

    printf("\n %d - finished \n", getpid());

    if (argc > 1) {
        sleep(10);
        del_semvalue();//删除信号量
    }
}

//函数:设置信号量的值
static int set_semvalue(void) {
    union semun sem_union;
    sem_union.val = 1;

    if (semctl(sem_id, 0, SETVAL, sem_union))
        return 0;

    return 1;
}

//函数:删除信号量
static void del_semvalue(void) {
    union semun sem_union;

    if (semctl(sem_id, 0, IPC_RMID, sem_union))
        fprintf(stderr, "Failed to delete semaphore\n");
}

//函数:信号量P操作:对信号量进行减一操作
static int semaphore_p(void) {
    struct sembuf sem_b;

    sem_b.sem_num = 0;//信号量编号
    sem_b.sem_op = -1;//P操作
    sem_b.sem_flg = SEM_UNDO;

    if (semop(sem_id, &sem_b, 1) == -1) {
        fprintf(stderr, "semaphore_p failed\n");
        return 0;
    }

    return 1;
}

//函数:信号量V操作:对信号量进行加一操作
static int semaphore_v(void) {
    struct sembuf sem_b;

    sem_b.sem_num = 0;//信号量编号
    sem_b.sem_op = 1;//V操作
    sem_b.sem_flg = SEM_UNDO;

    if (semop(sem_id, &sem_b, 1) == -1) {
        fprintf(stderr, "semaphore_v failed\n");
        return 0;
    }

    return 1;

}

 

 

 1 /*
 2  * semtest.cpp
 3  *
 4  *  Created on: Jun 27, 2013
 5  *      Author: zsf
 6  */
 7 
 8 #include <stdio.h>
 9 #include <stdlib.h>
10 #include <sys/types.h>
11 #include <sys/ipc.h>
12 #include <sys/sem.h>
13 #include <sys/stat.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16 #include <string.h>
17 #include <strings.h>
18 
19 union semun {
20         int val;
21         struct semid_ds *buf;
22         unsigned short int *array;
23         struct seminfo *__buf;
24 };
25 
26 int main(void) {
27     char* buf_child[] = { "this""is""the""child""process" };
28     char* buf_father[] = { "father""say""hello""to""child" };
29     int i = 0, semid, fd;
30     pid_t pid;
31     struct sembuf sb; //信号量操作
32     union semun sem;
33     semid = semget(100020666 | IPC_CREAT); //申请信号量组,包含2个信号量
34 
35     sem.val = 0;
36     semctl(semid, 0, SETVAL, sem); //初始化0号信号量为0
37     sem.val = 1;
38     semctl(semid, 1, SETVAL, sem); //初始化1号信号量为1
39 
40     fd = open("./tmp", O_CREAT | O_TRUNC | O_WRONLY, 0666);
41 
42     pid = fork();
43     switch (pid) {
44         case -1:
45             perror("fork fail");
46             break;
47         case 0/* child consume */
48             srand((unsigned int) getpid());
49             while (i < 5) {
50                 sb.sem_num = 1//将1号信号量
51                 sb.sem_op = -1//减1
52                 sb.sem_flg = sb.sem_flg & ~IPC_NOWAIT;
53                 semop(semid, &sb, 1);
54 
55                 write(fd, buf_child[i], strlen(buf_child[i]));
56                 sleep(rand());
57                 write(fd, &" "1);
58                 i++;
59 
60                 sb.sem_num = 0//将0号信号量
61                 sb.sem_op = 1//加1
62                 sb.sem_flg = sb.sem_flg & ~IPC_NOWAIT;
63                 semop(semid, &sb, 1); //操作信号量
64             }
65             break;
66         default:/* parent production  */
67             srand((unsigned int) getpid());
68             while (i < 5) {
69                 sb.sem_num = 0//将0号信号量
70                 sb.sem_op = -1//减1
71                 sb.sem_flg = sb.sem_flg & ~IPC_NOWAIT;
72                 semop(semid, &sb, 1); //操作信号量
73 
74                 write(fd, buf_father[i], strlen(buf_father[i]));
75                 sleep(rand());
76                 write(fd, &" "1);
77                 i++;
78 
79                 sb.sem_num = 1;
80                 sb.sem_op = 1;
81                 sb.sem_flg = sb.sem_flg & ~IPC_NOWAIT;
82                 semop(semid, &sb, 1);
83             }
84             break;
85     }
86     return 0;
87 }
View Code

 

 

posted on 2013-06-27 14:50  凌峰布衣  阅读(760)  评论(0编辑  收藏  举报

导航