(源码)用管道连成进程环,改进后可以模拟令牌环网

34 views
Skip to first unread message

李剑峰

unread,
Oct 20, 2008, 10:46:19 AM10/20/08
to 西邮操作系统课程论坛
#include<errno.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>

int main(int argc,char *argv[]){
pid_t childpid;
int error;
int fd[2];
int i;
int nprocs;

if((argc!=2)||((nprocs=atoi(argv[1]))<=0)){
fprintf(stderr,"Usage:%s nprocs\n",argv[0]);
return 1;
}
if(pipe(fd)==-1){
perror("Failed to create starting pipe");
return 1;
}
if((dup2(fd[0], STDIN_FILENO)==-1)||
(dup2(fd[1], STDOUT_FILENO)==-1)){
perror("Failed to connect pipe");
return 1;
}
for(i=1;i<nprocs;i++){
if(pipe(fd)==-1){
fprintf(stderr,"[%ld]:failed to create pipe %d:%s\n",
(long)getpid(),i,strerror(errno));
return 1;
}
if((childpid=fork())==-1){
fprintf(stderr, "[%ld]:failed to create child %d:%s\n",
(long)getpid(),i,strerror(errno));
return 1;
}
if(childpid>0)error=dup2(fd[1],STDOUT_FILENO);
else error=dup2(fd[0],STDIN_FILENO);
if(error==-1){
fprintf(stderr, "[%ld]:failed to dup pipes for iteration %d: %s\n",
(long)getpid(),i,strerror(errno));
return 1;
}
if((close(fd[0])==-1)||(close(fd[1])==-1)){
fprintf(stderr, "[%ld]:failed to close extra descriptors %d: %s\n",
(long)getpid(),i,strerror(errno));
return 1;
}
if(childpid)
break;
}
fprintf(stderr, "this is process %d with ID %ld and parent id %ld\n",
i,(long)getpid(),(long )getppid());
return 0;
}


陈老师

unread,
Oct 20, 2008, 11:06:50 AM10/20/08
to xiyouo...@googlegroups.com


2008/10/20 李剑峰 <itismy...@gmail.com>

李则良

unread,
Oct 21, 2008, 2:59:03 AM10/21/08
to xiyouo...@googlegroups.com
2008/10/20 李剑峰 <itismy...@gmail.com>:
这个例子很不错。
只是有一点缺点就是运行不稳定:
例如我把代码存为了t.c
lzel@lzel-desktop:/media/LZEL_U/os_test/test$ gcc -o t t.c // 编译
lzel@lzel-desktop:/media/LZEL_U/os_test/test$ ./t 10 //创建10个进程 第一次运行
this is process 5 with ID 18393 and parent id 18392
this is process 7 with ID 18395 and parent id 18394
this is process 10 with ID 18398 and parent id 18397
this is process 6 with ID 18394 and parent id 1
this is process 2 with ID 18390 and parent id 18389
this is process 3 with ID 18391 and parent id 18390
this is process 4 with ID 18392 and parent id 18391
this is process 1 with ID 18389 and parent id 16273
this is process 8 with ID 18396 and parent id 1
this is process 9 with ID 18397 and parent id 1
lzel@lzel-desktop:/media/LZEL_U/os_test/test$ ./t 10 //第二次运行
this is process 10 with ID 18412 and parent id 18411
this is process 4 with ID 18406 and parent id 18405
this is process 3 with ID 18405 and parent id 18404
this is process 5 with ID 18407 and parent id 1
this is process 8 with ID 18410 and parent id 18409
this is process 6 with ID 18408 and parent id 1
this is process 7 with ID 18409 and parent id 1
this is process 9 with ID 18411 and parent id 1
this is process 2 with ID 18404 and parent id 18403
this is process 1 with ID 18403 and parent id 16273
lzel@lzel-desktop:/media/LZEL_U/os_test/test$ ./t 10
this is process 1 with ID 18413 and parent id 16273
this is process 10 with ID 18422 and parent id 18421
lzel@lzel-desktop:/media/LZEL_U/os_test/test$ this is process 2 with
ID 18414 and parent id 1 //第三次运行
this is process 5 with ID 18417 and parent id 18416
this is process 7 with ID 18419 and parent id 18418
this is process 6 with ID 18418 and parent id 18417
this is process 8 with ID 18420 and parent id 1
this is process 9 with ID 18421 and parent id 18420
this is process 4 with ID 18416 and parent id 18415
this is process 3 with ID 18415 and parent id 1

lzel@lzel-desktop:/media/LZEL_U/os_test/test$
分析了一下,看到有一些进程的parent id 为 1,就知道父进程没有等待子进程就先行归西了:-),造成了大量的孤儿进程被1号init进程收养了。
我做了一些改进:
lzel@lzel-desktop:/media/LZEL_U/os_test/test$ cat lzel.c
#include <unistd.h>


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/wait.h>
#include <errno.h>

int main(int argc,char *argv[])
{

pid_t child_pid;


int error;
int fd[2];
int i;
int nprocs;

if ((argc != 2) || ((nprocs = atoi(argv[1])) <= 0) ) {

fprintf(stderr,"Usage: %s ${nprocs}\n",argv[0]);


return 1;
}
if (pipe(fd) == -1) {

perror("failed to pipe");
return 1;
}
if ((dup2(fd[0],STDIN_FILENO) == -1) || (dup2(fd[1],STDOUT_FILENO) == -1)) {
perror("failed to dup pipe");
return 1;
}
if ((close(fd[0]) == -1) || (close(fd[1]) == -1)) {
perror("failed to close fd");
return 1;
}
for (i = 1; i < nprocs; i++) {
if (pipe (fd) == -1) {


fprintf(stderr,"[%ld]: failed to create pipe %d: %s
\n",(long)getpid(),i,strerror(errno));
return 1;
}

if ((child_pid = fork()) == -1) {


fprintf(stderr,"[%ld]: failed to create child %d:
%s\n",(long)getpid(),i,strerror(errno));
return 1;
}

if (child_pid > 0)
error = dup2(fd[1],STDOUT_FILENO);
else
error = dup2(fd[0],STDIN_FILENO);
if (error == -1) {


fprintf(stderr,"[%ld]: failed to dup pipes for iteration %d:
%s\n",(long)getpid(),i,strerror(errno));
return 1;
}

if ((close(fd[0]) == -1) || (close(fd[1]) == -1)) {


fprintf(stderr, "[%ld]:failed to close extra descriptors %d: %s\n",
(long)getpid(), i, strerror(errno));
return 1;
}

if (child_pid != 0)
break;
}
if(child_pid != 0) {
wait(NULL);


fprintf(stderr, "this is process %d with ID %ld and parent id
%ld\n",i,(long)getpid(),(long )getppid());
}
return 0;
}

lzel@lzel-desktop:/media/LZEL_U/os_test/test$ gcc -o lzel lzel.c //编译
lzel@lzel-desktop:/media/LZEL_U/os_test/test$ ./lzel 10 //创建10个进程 第一次运行
this is process 9 with ID 18540 and parent id 18539
this is process 8 with ID 18539 and parent id 18538
this is process 7 with ID 18538 and parent id 18537
this is process 6 with ID 18537 and parent id 18536
this is process 5 with ID 18536 and parent id 18535
this is process 4 with ID 18535 and parent id 18534
this is process 3 with ID 18534 and parent id 18533
this is process 2 with ID 18533 and parent id 18532
this is process 1 with ID 18532 and parent id 16273
lzel@lzel-desktop:/media/LZEL_U/os_test/test$ ./lzel 10 //第二次运行
this is process 9 with ID 18559 and parent id 18558
this is process 8 with ID 18558 and parent id 18557
this is process 7 with ID 18557 and parent id 18556
this is process 6 with ID 18556 and parent id 18555
this is process 5 with ID 18555 and parent id 18554
this is process 4 with ID 18554 and parent id 18553
this is process 3 with ID 18553 and parent id 18552
this is process 2 with ID 18552 and parent id 18551
this is process 1 with ID 18551 and parent id 16273
lzel@lzel-desktop:/media/LZEL_U/os_test/test$ ./lzel 10 //第三次运行
this is process 9 with ID 18573 and parent id 18572
this is process 8 with ID 18572 and parent id 18571
this is process 7 with ID 18571 and parent id 18570
this is process 6 with ID 18570 and parent id 18569
this is process 5 with ID 18569 and parent id 18568
this is process 4 with ID 18568 and parent id 18567
this is process 3 with ID 18567 and parent id 18566
this is process 2 with ID 18566 and parent id 18565
this is process 1 with ID 18565 and parent id 16273
lzel@lzel-desktop:/media/LZEL_U/os_test/test$
没有出现你的那种情况,关键代码只是在父进程退出前加上一句wait(NULL); 等待它的子进程退出。
关于wait的详细用法在这里:
http://groups.google.com/group/xiyouoscourse/web/%E7%B3%BB%E7%BB%9F%E8%B0%83%E7%94%A8%E8%B7%9F%E6%88%91%E5%AD%A6(3)
系统调用跟我学(3)

Reply all
Reply to author
Forward
0 new messages