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
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- union semun
- {
- int val;
- struct semid_ds *buf;
- unsigned short int *array;
- struct seminfo *__buf;
- };
- int main(void)
- {
- char* buf_child[]={ "this", "is", "the", "child", "process"};
- char* buf_father[]={ "father", "say", "hello", "to", "child"};
- int i = 0, semid, fd;
- pid_t pid;
- struct sembuf sb; //信号量操作
- union semun sem;
- semid = semget(1000, 2, 0666 | IPC_CREAT); //申请信号量组,包含2个信号量
- sem.val = 0;
- semctl(semid, 0, SETVAL, sem); //初始化0号信号量为0
- sem.val = 1;
- semctl(semid, 1, SETVAL, sem); //初始化1号信号量为1
- fd=open("tmp",O_CREAT|O_TRUNC|O_WRONLY,0666);
- pid = fork();
- switch (pid) {
- case -1:
- perror("fork fail");
- break;
- case 0: /* child consume */
- srand((unsigned int)getpid());
- while (i < 5) {