操作系统实验资料搜集:信号量,生产者消费者,读者写者等

博客介绍了如何在Linux环境下使用C语言通过信号量解决生产者消费者问题,详细讲解了信号量的概念、初始化、应用步骤,并提供了多个并发控制问题的示例,如单缓冲区、多生产者多消费者、哲学家进餐和读者写者问题。还讨论了信号量、自旋锁和互斥锁在并发控制中的应用。
摘要由CSDN通过智能技术生成

Linux C 进程间通信: 生产者消费者问题

转自http://www.cnblogs.com/lycheng/archive/2011/11/23/2260656.html

有两个生产者,一个写入大写字母,另一个写入小写。

有三个消费者,一个消费大写字母,一个消费小写字母,还有一个不分大小写消费。

 

复制代码
#include <stdlib.h>
#include <sys/mman.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <linux/sem.h>
#include <sys/types.h>

#define MAX_PRODUCTS 10
struct sembuf buf;

int down(int sem_id)
{
buf.sem_num = 0;
buf.sem_op = -1;
buf.sem_flg = SEM_UNDO;
if (semop(sem_id, &buf, 1) == -1)
{
perror("Down failed!/n");
return 0;
}
return 1;
}
int up(int sem_id)
{
buf.sem_num = 0;
buf.sem_op = 1;
buf.sem_flg = SEM_UNDO;
if (semop(sem_id, &buf, 1) == -1)
{
perror("Up failed!/n");
return 0;
}
return 1;
}

void main()
{
union semun arg;
pid_t producer1, producer2;
pid_t consumer1, consumer2, consumer3;

int mutex;
int full;
int empty;
char *buffer;

// 共享内存
buffer = (char*) mmap(NULL, sizeof(char) * MAX_PRODUCTS,
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
int i;
for (i = 0; i < MAX_PRODUCTS; i++)
buffer[i] = '';

// 创建信号量
mutex = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT);
full = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT);
empty = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT);
arg.val = 1;
if (semctl(mutex, 0, SETVAL, arg) == -1)
{
perror("set the mutex error\n");
return;
}
arg.val = 0;
if (semctl(full, 0, SETVAL, arg) == -1)
{
perror("set the full error\n");
return;
}
arg.val = MAX_PRODUCTS;
if (semctl(empty, 0, SETVAL, arg) == -1)
{
perror("set the empty error/n");
return;
}

if ((producer1 = fork()) == 0)
{
// 写入大写字母
while (1)
{
down(empty);
down(mutex);
srand(time(NULL));
int offset = rand() % 26;
char item = 'A' + offset;
int j;
for (j = 0; j < MAX_PRODUCTS; j++)
{
if (buffer[j] == '')
{
buffer[j] = item;
printf("Producer A insert letter: %c\n", item);
break;
}
}
up(mutex);
up(full);
sleep(1);
}
}
else if ((producer2 = fork()) == 0)
{
// 写入小写字母
while (1)
{
down(empty);
down(mutex);
srand(time(NULL));
int offset = rand() % 26;
char item = 'a' + offset;
int j;
for (j = 0; j < MAX_PRODUCTS; j++)
{
if (buffer[j] == '')
{
buffer[j] = item;
printf("Producer B insert letter: %c\n", item);
break;
}
}
up(mutex);
up(full);
sleep(1);
}
}
else if ((consumer1 = fork()) == 0)
{
// 消费大写字母
while (1)
{
down(full);
down(mutex);
char item;
int j;
for (j = 0; j < MAX_PRODUCTS; j++)
{
if (buffer[j] >= 'A' && buffer[j] <= 'Z')
{
item = buffer[j];
buffer[j] = '';
break;
}
}
printf("Consumer A removes letter: %c\n", item);
up(mutex);
up(empty);
sleep(2);
}
}
else if ((consumer2 = fork()) == 0)
{
// 消费小写字母
while (1)
{
down(full);
down(mutex);
char item;
int j;
for (j = 0; j < MAX_PRODUCTS; j++)
{
if (buffer[j] >= 'a' && buffer[j] <= 'z')
{
item = buffer[j];
buffer[j] = '';
break;
}
}
printf("Consumer B removes letter: %c\n", item);
up(mutex);
up(empty);
sleep(2);
}
}
else if ((consumer3 = fork()) == 0)
{
// 大小写字母
while (1)
{
down(full);
down(mutex);
char item;
int j;
for (j = 0; j < MAX_PRODUCTS; j++)
{
if (buffer[j] != '')
{
item = buffer[j];
buffer[j] = '';
break;
}
}
printf("Consumer C removes letter: %c\n", item);
up(mutex);
up(empty);
sleep(2);
}
}
else
{
// 主进程
while (1)
{
int j;
printf("Buffer: ");
for (j = 0; j < MAX_PRODUCTS; j++)
{
printf("%c ", buffer[j]);
}
printf(" \n");
sleep(10);
}
}
}
复制代码


参考: http://www.ibm.com/developerworks/cn/linux/l-ipc/part5/index1.html#3 共享内存

这个生产者消费者问题用线程实现起来会容易很多,进程间通信的话涉及到共享内存的问题。还有生成随机数的问题还是很纠结的,不知道为什么大小写生产者都是生成同一个字母。



linux的进程通信:信号量实例(C语言)

转自http://hector.blog.51cto.com/4229131/758930

这篇发的很纠结,这不是我原创的代码,是同学写的,我只是想在这记录下来,以后没事可以看看,写转载嘛,又没有转载的来源,翻译就更扯了,勉强写个原创,其实不是我原创啦。 ( ̄▽ ̄)" 有兴趣可以看下,这是关于linux中的信号量的使用的一篇文章。我加了一些注释。

题目是:写一个程序,该程序创建两个进程,分别打印"this is the child process"和"father say hello to child",要求交替打印,输出成"this father is say the hello child to process child",每打印一个单词进程阻塞一段时间。将输出打印到当前目录下的tmp文件中。

答:

    
    
    
  1. #include <stdio.h> 
  2. #include <stdlib.h> 
  3. #include <sys/types.h> 
  4. #include <sys/ipc.h> 
  5. #include <sys/sem.h> 
  6. #include <sys/stat.h> 
  7. #include <fcntl.h> 
  8.  
  9. union semun 
  10.     int val; 
  11.     struct semid_ds *buf; 
  12.     unsigned short int *array; 
  13.     struct seminfo *__buf; 
  14. }; 
  15.  
  16. int main(void
  17.     char* buf_child[]={ "this""is""the""child""process"}; 
  18.     char* buf_father[]={ "father""say""hello""to""child"}; 
  19.     int i = 0, semid, fd; 
  20.     pid_t pid; 
  21.     struct sembuf sb; //信号量操作
  22.     union semun sem; 
  23.     semid = semget(1000, 2, 0666 | IPC_CREAT); //申请信号量组,包含2个信号量
  24.  
  25.     sem.val = 0; 
  26.     semctl(semid, 0, SETVAL, sem); //初始化0号信号量为0
  27.     sem.val = 1; 
  28.     semctl(semid, 1, SETVAL, sem); //初始化1号信号量为1
  29.  
  30.     fd=open("tmp",O_CREAT|O_TRUNC|O_WRONLY,0666); 
  31.  
  32.     pid = fork(); 
  33.     switch (pid) { 
  34.         case -1: 
  35.             perror("fork fail"); 
  36.             break
  37.         case 0: /* child consume */ 
  38.             srand((unsigned int)getpid()); 
  39.             while (i < 5) { 
《生产者与消费者问题算法实现》 设计思想 因为有多个缓冲区,所以生产者线程没有必要在生成新的数据之前等待最后一个数据被消费者线程处理完毕。同样,消费者线程并不一定每次只能处理一个数据。在多缓冲区机制下,线程之间不必互相等待形成死锁,因而提高了效率。   多个缓冲区就好像使用一条传送带替代托架,传送带上一次可以放多个产品。生产者在缓冲区尾加入数据,而消费者则在缓冲区头读取数据。当缓冲区满的时候,缓冲区就上锁并等待消费者线程读取数据;每一个生产或消费动作使得传送带向前移动一个单位,因而,消费者线程读取数据的顺序和数据产生顺序是相同的。 可以引入一个count计数器来表示已经被使用的缓冲区数量。用hNotEmptyEvent 和hNotFullEvent 来同步生产者和消费者线程。每当生产者线程发现缓冲区满( count=BufferSize ),它就等待hNotEmptyEvent 事件。同样,当消费者线程发现缓冲区空,它就开始等待hNotEmptyEvent。生产者线程写入一个新的数据之后,就立刻发出hNotEmptyEvent 来唤醒正在等待的消费者线程;消费者线程在读取一个数据之后,就发出hNotFullEvent 来唤醒正在等待的生产者线程。 程序的设计思想大致为:设置一while循环,pi生产者访问临界区,得到权限访问缓冲区,如果缓冲区满的,则等待,直到缓冲区非满;访问互斥锁,当得到互斥锁且缓冲区非满时,跳出while循环,开始产生新数据,并把数据存放于Buffer缓冲区,当数据存放结束则结束临界区;接着唤醒消费者线程;ci消费者访问临界区,得到权限访问缓冲区,如果缓冲区为空,没有可以处理的数据,则释放互斥锁且等待,直到缓冲区非空;当等到缓冲区非空时,跳出while循环;消费者获得数据,并根据所获得的数据按类别消费(当消费者获得的数据为大写字母时,则把大写字母转换成小写字母,并显示;当消费者获得的数据为小写字母时,则把小写字母转换成大写字母,并显示;当消费者获得的数据为字符0、1、2、……8、9时,把这些字符直接显示到屏幕;当消费者获得的数据为符号(+、-、*、\……)时,把这些符号打印成7行7列的菱形);处理完数据后,结束临界区;接着唤醒生产者线程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值