Linux 信号量 生产者消费者小例题 (嘘,我是菜鸟~)

  菜鸟偶遇信号量,擦出火花(只有不熟才会有火花)。于是上网搜资料和看《Unix环境高级编程》实现了几个小例题,高手请勿喷!这几位写得非常好啊:

题目来源: http://www.it165.net/os/html/201312/7039.html

信号量及其用法:http://www.cnblogs.com/hjslovewcl/archive/2011/03/03/2314341.html

Mutex与Semaphore区别著名的厕所理论:http://koti.mbnet.fi/niclasw/MutexSemaphore.html

  哎呀,暴露了!我不是故意偷窥别人的……





一:一个生产者、一个消费者、一个资源情况

  这种情况情况可以只用一个信号量,要生成或要消费只用尝试获取这个信号量,这里用了两个:full=1和empty=0,两个只为了和后面一致,1、0是赋初值。生产者和消费者情况如下:

//生产者:
P(empty)
    生成资源并放进资源处
V(full)

//消费者:
P(full)
    消费资源
V(empty)

  若生产者最先开始生产资源,P(empty),full和empty都成了0,此时若消费者想要消费,则P(full)时,full为0则睡眠等待,等生产者生结束就把full加1,看到消费者可怜地睡着了就唤醒它,然后消费者把full减1自己快活去了。

  消费者消费过程中生产者若要生了,则会因为empty为0而休眠,等消费者结束就把empty加1,然后生产者开始生产。

  上面的好理解,下面上代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

#include <x86_64-linux-gnu/sys/types.h>
#include <x86_64-linux-gnu/sys/ipc.h>
#include <x86_64-linux-gnu/sys/sem.h>

int semInite(int semId, int value);
int semDelete(int semId);
int semP(int semId);
int semV(int semId);

//declare a union to be used
union semun
{
    int val;                        /* value for SETVAL */
    struct semid_ds *buf;                /* buffer for IPC_STAT, IPC_SET */
    unsigned short int *array;         /* array for GETALL, SETALL */
    struct seminfo *__buf;                /* buffer for IPC_INFO */
};

//semaphore declare
static int semFullId;
static int semEmptyId;
static int source = 0;        //source definition    

//new thread as a consumer
void* child_thread(void* arg)
{
    int ttt = 1;

    while(1)
    {
        sleep(rand() % 19);
        printf("child No.%d times wants to consume...\n", ttt);

        semP(semFullId);    //
        printf("child No.%d times start consuming. source = %d\n", ttt, source);
        source = 0;
        printf("child No.%d times end consuming. source = %d\n\n", ttt++, source);
        semV(semEmptyId);    //
    }

    return (void*)0;
}

int main(void)
{
    //create semaphore
    semFullId = semget((key_t)1235, 1, 0666 | IPC_CREAT);
    semEmptyId = semget((key_t)1236, 1, 0666 | IPC_CREAT);
    semInite(semFullId, 0);
    semInite(semEmptyId, 1);

    pthread_t pid;
    pthread_create(&pid, NULL, child_thread, NULL);

    int tt = 1;
    while(1)
    {
        sleep(rand() % 18);
        printf("parent No.%d times wants to produce...\n", tt);

        semP(semEmptyId);    //
        printf("parent No.%d times start producing. source = %d\n", tt, source);
        source = rand() % 100;
        printf("parent No.%d times end producing. source = %d\n", tt++, source);
        semV(semFullId);    //
    }

    semDelete(semFullId);
    semDelete(semEmptyId);
    return 0;
}

//set semaphore as default value
int semInite(int semId, int value)
{
    union semun semUnion;
    semUnion.val = value;    //set default semaphore
    return semctl(semId, 0, SETVAL, semUnion);
}

//delete semaphore
int semDelete(int semId)
{
    union semun semUnion;
    return semctl(semId, 0, IPC_RMID, semUnion);
}

//semaphore P operation
int semP(int semId)
{
    struct sembuf semBuf;
    semBuf.sem_num = 0;        //indicate it is not semaphore array
    semBuf.sem_op = -1;        //subtract one
    semBuf.sem_flg = SEM_UNDO;

    return semop(semId, &semBuf, 1);    //return value
}

//semaphore V operation
int semV(int semId)
{
    struct sembuf semBuf;
    semBuf.sem_num = 0;        //indicate it is not semaphore array
    semBuf.sem_op = 1;        //subtract one
    semBuf.sem_flg = SEM_UNDO;

    return semop(semId, &semBuf, 1);    //return value
}

111

两个线程,创建的新线程当做消费者了。其中unix的几个信号量的函数看了半天,有点复杂,简单不准确来讲:

//获得一个信号量啦,第二个参数是想要创建的信号量个数,
//因为unix操作的是信号量集合,设为1不就一个信号量了嘛
//其他参数我不管了
int semget(key_t key, int num_sems, int sem_flags);

//信号量集合的操作,这个可以用来实现P、V的 +1 -1 的功能
int semop(int sem_id, struct sembuf *sem_ops, size_t num_sem_ops);

//信号量集合的控制,如初始化删除等
int semctl(int sem_id, int sem_num, int command, ...);

运行:

Linux 信号量 生产者消费者小例题 (嘘,我是菜鸟~)

时间: 2024-08-09 11:07:30

Linux 信号量 生产者消费者小例题 (嘘,我是菜鸟~)的相关文章

LINUX学习:生产者&amp;消费者模型复习

回顾一下生产者消费者模型. #include <stdio.h> #include <stdlib.h> #include <string.h> #include <semaphore.h> #include <unistd.h> #include <sys/types.h> #include <pthread.h> #define ERR_EXIT(m) do { perror(m); exit(EXIT_FAILURE

linux进程 生产者消费者

#include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<string.h> #include<fcntl.h> int lock_set(int fd,int type) { struct flock lock; lock.l_whence= SEEK_SET; lock.l_start = 0; lock.l_len = 0; lock.l_type = type; lo

linux ptheard 生产者消费者

1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <pthread.h> 4  5 pthread_mutex_t mutex; 6 pthread_cond_t cond_full; 7 pthread_cond_t cond_empty; 8  9 int g_iBufSize = 0;10 11 void *thread_producer(void* arg)12 {13     while(true)14

【操作系统】经典的同步问题(生产者消费者问题, 哲学家进餐问题, 读写问题)

用专业术语来说, 进程是程序的一次动态执行.说简单点, 就是进程是系统中的某个任务.操作系统中有多个任务需要执行, 那么怎样执行才能使它们同步呢? 即如何让任务并发执行互不影响呢? 这就引出了进程同步中的经典问题: 生产者消费者问题, 哲学家进餐问题, 读写问题 生产者-消费者问题 有一群生产者进程在生产产品, 并将这些产品提供给消费者进程取消费. 为使生产者进程与消费者进程能并发进行, 在两者间设置了一个具有n个缓冲区的缓冲池, 生产者进程将其所生产的产品翻入缓冲区中, 消费者进程可从一个缓冲

Linux多线程实践(5) --Posix信号量与互斥量解决生产者消费者问题

Posix信号量 Posix 信号量 有名信号量 无名信号量 sem_open sem_init sem_close sem_destroy sem_unlink sem_wait sem_post 有名信号量 #include <fcntl.h> /* For O_* constants */ #include <sys/stat.h> /* For mode constants */ #include <semaphore.h> sem_t *sem_open(co

Linux下用环形buf以及POSIX版本信号量解决生产者消费者问题

一.Semaphore(信号量) Mutex变量是非0即1的,可看作一种资源的可用数量,初始化时Mutex是1,表示有一个可用资源, 加锁时获得该资源,将Mutex减到0,表示不再有可用资源,解锁时释放该资源,将Mutex重新加到1,表示又有了一个可用资源. 信号量(Semaphore)和Mutex类似,表示可用资源的数量,和Mutex不同的是这个数量可以大于1. 即,如果信号量描述的资源数目是1时,此时的信号量和互斥锁相同! 本次使用的是POSIX semaphore库函数,这种信号量不仅可以

Linux线程编程之生产者消费者问题

前言 本文基于顺序循环队列,给出Linux生产者/消费者问题的多线程示例,并讨论编程时需要注意的事项.文中涉及的代码运行环境如下: 本文假定读者已具备线程同步的基础知识. 一  顺序表循环队列 1.1 顺序循环队列定义 队列是一种运算受限的先进先出线性表,仅允许在队尾插入(入队),在队首删除(出队).新元素入队后成为新的队尾元素,元素出队后其后继元素就成为队首元素. 队列的顺序存储结构使用一个数组和两个整型变量实现,其结构如下: 1 struct Queue{ 2 ElemType elem[M

用信号量解决生产者消费者问题

用信号量解决生产者消费者问题: ipc.h #ifndef _IPC_H_ #define _IPC_H_ #include <sys/types.h> #include <unistd.h> #include <sys/ipc.h> #include <sys/sem.h> #include <sys/shm.h> #include <errno.h> #include <stdio.h> #include <st

多线程实现生产者消费者问题 详细注释 事件+临界区 信号量+临界区2种方法

生产者消费者问题:  该问题描述了两个共享固定大小缓冲区的线程--即所谓的"生产者"和"消费者"--在实际运行时会发生的问题.生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程.与此同时,消费者也在缓冲区消耗这些数据.该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据.具体我就不解释了   应该都懂 不懂请百度一下 我是用事件实现生产者消费者问题的同步  用临界区实现互斥    我的这个做法与经典做法不同 即用信号量