2012.2.14 - LINUX内核 - 信号量的实现和应用

Posted on 2013-02-14 00:02  SnakeHunt2012  阅读(264)  评论(0)    收藏  举报

本文始作于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 }