本文始作于2012年2月14日,刊登于人人网,于2013年2月13日迁移至此
要求消费者的数量是个变量n,那就得用循环产生进程。
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 #include <sys/types.h> 5 6 void err_sys(char *); 7 8 main() 9 { 10 int i, n; 11 pid_t pid; 12 13 if ((pid = fork()) < 0) 14 err_sys("fork error"); 15 else if (pid == 0) { 16 /* 生产者 */ 17 printf("生产者 working...\n"); 18 } 19 else { 20 for (i = 0; i < 10; ++i) { 21 if ((pid = fork()) < 0) 22 err_sys("fork error"); 23 else if (pid == 0) { 24 /* 消费者 */ 25 printf("消费者 working...\n"); 26 break; 27 } 28 else; 29 } 30 } 31 return 0; 32 } 33 34 void err_sys(char *message) 35 { 36 printf("%s\n", message); 37 exit(0); 38 }
结果说明这样能成功产生固定数量的进程。
接下来测试文件访问,看fopen的文件能不能在多进程下跨进程使用,代码如下:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 #include <sys/types.h> 5 6 void err_sys(char *); 7 8 main() 9 { 10 int i, n; 11 pid_t pid; 12 FILE *fp; 13 14 fp = fopen("buffer", "w"); 15 if ((pid = fork()) < 0) 16 err_sys("fork error"); 17 else if (pid == 0) { 18 /* 生产者 */ 19 fprintf(fp, "This is productor.\n"); 20 } 21 else { 22 for (i = 0; i < 10; ++i) { 23 if ((pid = fork()) < 0) 24 err_sys("fork error"); 25 else if (pid == 0) { 26 /* 消费者 */ 27 fprintf(fp, "This is consulter %d.\n", i); 28 break; 29 } 30 else; 31 } 32 } 33 return 0; 34 } 35 36 void err_sys(char *message) 37 { 38 printf("%s\n", message); 39 exit(0); 40 }
不过后来实验指导书上说最好直接用系统调用,那好吧,就用系统调用吧,那这样的话就得先弄明白系统调用怎么使用,这又一篇文章,在网上搜的,基本上解决了所有问题。Linux系统调用(一)—文件读写操作:http://www.am82.com/4265/ 还有:13.4.8 "Read(读)"系统调用:http://book.51cto.com/art/200907/133425.htm
现在面临这几个问题。首先,怎么在内核态实现malloc(),因为我需要在内核的堆栈段创建信号量的结构体,关于这个我在网上看在头文件linux/slab.h下有一个内核函数void *kmalloc(size_t size, int flags);能实现标准函数库里malloc()的功能。这又一篇文章是关于这个的:【Linux】在内核中申请内存 :http://blog.csdn.net/newfeicui/article/details/6437917 。然后就是写完sem.c之后,怎么写Makefile就又是个问题,因为不了解C语言在连接多个源代码文件的时候应该怎么设置的,更不了解如果要将sem跟他需要的代码连接在一起,就是一起编译,在Makefile里应该怎么写,以及应该跟哪些代码连在一起也不知道该怎么找。然后还有,就是在编写pc.c的时候,生产者还好说,就是在模拟缓冲的文件里写东西,但是消费者是要在里面删东西的啊,这删除好像fprintf()不能完成吧,就得想别的办法了。最后就是sunner提到的这几个sem_*函数怎么用,我在网上找都没有中文的,我发邮件问sunner,他说就看英文的,这是个锻炼的机会,至于我问他为什么man在找open()命令的时候为什么找不到,他说我少安装了个manpages-dev包,其实他想说的是manpage-posix-dev软件包,因为manpages-dev我检查发现已经安过了,最后在baidu上找到了很罕见的中文的解释这几个sem_*命令的博客:POSIX semaphore: sem_open, sem_close, sem_post, sem_wait:http://www.cnblogs.com/BloodAndBone/archive/2011/01/18/1938552.html
经过好几天的努力最终确定pc.c的大概雏形:
1 #include <stdio.h> 2 #include <string.h> 3 #include <pthread.h> 4 #include <stdlib.h> 5 #include <fcntl.h> 6 #include <unistd.h> 7 #include <semaphore.h> 8 #include <sys/types.h> 9 #include <sys/stat.h> 10 11 void err_sys(char *); 12 13 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 14 15 main() 16 { 17 int i, j, n, buf, fd, cfo; 18 pid_t pid; 19 sem_t *full; 20 sem_t *empty; 21 //sem_t *mutex; 22 23 n = 5; 24 fd = open("/home/spiderhunt2011/lab/buffer", O_RDWR); 25 //mutex = sem_open("mutex", O_CREAT, 0644, 1); 26 full = sem_open("full", O_CREAT, 0644, 0); 27 empty = sem_open("empty", O_CREAT, 0644, 10); 28 29 if ((pid = fork()) == 0) { 30 /* 生产者 */ 31 for (i = 0; i < 100; ++i) { 32 pthread_mutex_lock(&mutex); 33 //sem_wait(mutex); 34 sem_wait(empty); 35 cfo = lseek(fd, 0, SEEK_CUR); 36 lseek(fd, 0, SEEK_END); 37 write(fd, &i, sizeof(int)); 38 lseek(fd, cfo, SEEK_SET); 39 //printf("process: 生产者%d\twrite: %d\n", i, i); 40 sem_post(full); 41 //sem_post(mutex); 42 pthread_mutex_unlock(&mutex); 43 } 44 } 45 else { 46 /* 消费者 */ 47 for (i = 0; i < n; ++i) { 48 if (fork() == 0) { 49 while (1) { 50 pthread_mutex_lock(&mutex); 51 //sem_wait(mutex); 52 sem_wait(full); 53 read(fd, &buf, sizeof(int)); 54 printf("process: 消费者%d\tread: %d\n", i, buf); 55 fflush(stdout); 56 sem_post(empty); 57 //sem_post(mutex); 58 pthread_mutex_unlock(&mutex); 59 } 60 break; 61 } 62 } 63 } 64 printf("主程序结束\n"); 65 sem_unlink("empty"); 66 sem_unlink("full"); 67 }
浙公网安备 33010602011771号