- 实现从数字1到数字N的累加
filename : sum.c,可执⾏程序sum
Usage : ./sum -i 5 -n 10000 : 表⽰使⽤5个进程,计算从1加到10000的和
Result :1+2+3+…+10000 = ?
- 每个进程都参与计算
- 不能对业务进⾏拆分
- 每个进程都去抢着加
- 不能使⽤任何睡眠策略
- 不能规定进程的执⾏顺序
- 需要使⽤⽂件,参考flock的⽤法
代码实现:
#include#include #include #include #include #include #include #include #include #define BUF_LEN 64 int main() { char buf[BUF_LEN] = "0 1"; int i = 1, temp = 0, pid;// i:当前待累加值,temp,当前累加结果 int fd = open("./sum", O_RDWR |O_CREAT | O_TRUNC, 0777); if(fd < 0) { perror("open"); exit(0); } write(fd, buf, BUF_LEN); //用父进程分别创建出五个子进程 for(int j = 1; j <= 5; j++) { pid = fork(); if(pid < 0) { perror("fork"); exit(1); } if(!pid) break; } if(pid) { //记得处理子进程僵尸进程 for(int j = 1; j <= 5; j++) waitpid(0, NULL, 0); //打印结果 lseek(fd, 0, SEEK_SET); if(read(fd, buf, BUF_LEN) < 0) { perror("read"); exit(1); } sscanf(buf, "%d %d", &temp, &i); //printf("%sn", buf); printf("sum = %dn", temp); close(fd); } else { //记得要重新调用open //否则因为子进程与父进程共享同一个文件打开表而导致互斥锁失效 close(fd); fd = open("./sum", O_RDWR); while(1) { if(flock(fd, LOCK_EX) != 0) { perror("flock"); exit(1); } //输出调试信息1 //printf("pid:[%d] arrive.n", getpid()); lseek(fd, 0, SEEK_SET); if(read(fd, buf, BUF_LEN) < 0) { perror("read"); exit(1); } sscanf(buf, "%d %d", &temp, &i); //输出调试信息2 //printf("%dn", i); if(i > 1000) { close(fd); exit(0); } temp += i++; sprintf(buf, "%d %d", temp, i); //printf("pid:[%d] %sn", getpid(), buf); lseek(fd, 0, SEEK_SET); if(write(fd, buf, BUF_LEN) < 0) { perror("write"); exit(1); } if(flock(fd, LOCK_UN) < 0) { perror("flock_UN"); exit(1); } } } return 0; }
心得:
踩了亿些坑 - -…,百度csdn找了好多份资料结果发现还是man手册香啊啊啊(虽然全英不友好)。
- PCB中保存着文件描述符表,调用fork创建子进程时子进程会继承复制一份文件描述符表到其PCB中。
- 文件描述符表指向文件打开描述符表,调用fork创建子进程时子进程和父进程共享同一份文件打开描述符表。
- 文件锁相关信息保存在文件打开描述符表中,若子进程用父进程的文件描述符对某文件进行互斥访问的话,会因为共享同一份文件打开描述符而导致互斥锁失效。



