Fork()编程

在Linux虚拟机上编写如下代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h> 
int main(int argc, char *argv[])
{  
   int i=0;  
   printf("i son/pa ppid pid  fpid\n");  
   //ppid指当前进程的父进程pid  
   //pid指当前进程的pid,  
   //fpid指fork返回给当前进程的值 
 
   for(i=0;i<4;i++)
   {  
       pid_t fpid=fork();  
    if(i<2)
    {
           if(fpid==0)  
        {
           printf("%d child  %4d %4d %4d\n",i,getppid(),getpid(),fpid);  
           sleep(3);
          
        }  
           else      
        {
           printf("%d parent %4d %4d %4d\n",i,getppid(),getpid(),fpid);  
           sleep(3);
        }
    }
    if(i==2)
    {
        if( fpid < 0 ){ // 出错
            perror("fork");
            exit(0);
        }
        if( fpid == 0 )
        {
            // 子进程
            {
                printf("%d son  %4d %4d %4d\n",i,getppid(),getpid(),fpid);  
                   sleep(3);
            }
            _exit(2); // 子进程退出,数字 2 为子进程退出的状态
        }
        else if( fpid > 0)
        {
            printf("%d papa %4d %4d %4d\n",i,getppid(),getpid(),fpid);  
               sleep(3);
             // 父进程
            int status = 0;
            wait(&status); 
            if(WIFEXITED(status) != 0)
            { // 子进程是否正常终止
                printf("son process return %d\n", WEXITSTATUS(status));
                printf("%d son  %4d %4d %4d\n",i,getppid(),getpid(),fpid);  
                sleep(3);
            }
            printf("this is father process\n");    
            printf("%d papa  %4d %4d %4d\n",i,getppid(),getpid(),fpid);  
            sleep(3);
        }
    }
    if(i==3)
    {
        if(fpid==0)  
        {
           printf("%d child  %4d %4d %4d\n",i,getppid(),getpid(),fpid);  
           sleep(3);      
        }  
        else      
        {
           printf("%d parent %4d %4d %4d\n",i,getppid(),getpid(),fpid);  
           sleep(3);
        }
        printf("*****before exec******\n\n");
        execl("/bin/ls", "ls", "-a", "-l", "-h", NULL);    
        perror("execl");
        printf("*****after exec*******\n\n");        
    } 
}
   return 0;  
}

运行结果图:

 


 

该程序的循环中,i<2时,一共建立了四个进程,打印六次。其中i代表循环次数,son/pa代表是父进程或是子进程,ppid代表父进程的pid,pid代表当前进程的pid,fpid指fork返回给当前进程的值。第一步:在父进程中,指令执行到for循环中,i=0,接着执行fork,fork执行完后,系统中出现两个进程,分别是3737和3738.可以看到父进程3737的父进程是3700,子进程3738的父进程正好是3737。我们用一个链表来表示这个关系:3700->4150->4151,第二次fork()后与第一次相类似,链表关系是:4150->4152, 4150->4151,4151->4153
其对应代码如下:
 
具体结果如下所示:
 

第三次循环中即i=2时,若是子进程就打印进程pid及其父进程,子进程,若是父进程,打印相关信息,并 调使用wait()函数,等子进程结束,回收子进程的资源,该函数会阻塞。
    status 某个字段保存子进程调用 _exit(2) 的 2,需要用宏定义取出
    waitpid(-1, &status, 0); // 和 wait() 没区别,0:阻塞
    waitpid(pid, &status, 0); // 指定等待进程号为 pid 的子进程, 0 阻塞
    waitpid(pid, &status, WNOHANG); // WNOHANG:不阻塞
如果子进程是正常终止的,取出的字段值非零,就执行以下命令
 
执行结果如下图所示
可以看出i==2时共有八个进程,其中子进程四个,父进程四个,回收了此次循环创建的子进程
 
第四次循环即i=3时,由于第二次循环已经收回了四个子进程,因此,在第三次,此前的四个进程重新创建了四个子进程,在这些进程中调用execl,其中
    /bin/ls:外部程序,这里是/bin目录的 ls 可执行程序,必须带上路径(相对或绝对)
    ls:没有意义,如果需要给这个外部程序传参,这里必须要写上字符串,至于字符串内容任意。
    -a,-l,-h:给外部程序 ls 传的参数
    NULL:这个必须写上,代表给外部程序 ls 传参结束
所用代码如下:
 
如果 execl() 执行成功,以下代码执行不到,因为当前进程已经被执行的 ls 替换了
 
运行结果如下所示,由于存在八个进程,因此调用了八次ls命令。
 
 

【实验目的】 1. 了解文件系统的原理; 2. 用高级语言编写和调试一个简单的文件系统,模拟文件管理的工作过程。从而对各种文件操作命令的实质内容和执行过程有比较深入的了解。 【实验准备】 1.文件的逻辑结构  顺序文件  索引文件  索引顺序文件  直接文件和哈希文件 2.外存分配方式  连续分配  链接分配  索引分配 【实验内容】 1. 实验要求 要求设计一个 n个用户的文件系统,每次用户可保存m个文件,用户在一次运行中只能打开一个文件,对文件必须设置保护措施,且至少有Create、delete、open、close、read、write等命令。 2. 实验题目  设计一个10个用户的文件系统,每次用户可保存10个文件,一次运行用户可以打开5个文件。  程序采用二级文件目录(即设置主目录[MFD])和用户文件目录(UED)。另外,为打开文件设置了运行文件目录(AFD)。  为了便于实现,对文件的读写作了简化,在执行读写命令时,只需改读写指针,并不进行实际的读写操作。 因系统小,文件目录的检索使用了简单的线性搜索。文件保护简单使用了三位保护码:允许读写执行、对应位为 1,对应位为0,则表示不允许读写、执行。程序中使用的主要设计结构如下:主文件目录和用户文件目录( MFD、UFD)打开文件目录( AFD)(即运行文件目录)。 M D F 用户名 文件目录指针 用户名 文件目录指针 U F D 文件名 保护码 文件长度 文件名 A F D 打开文件名 打开保护码 读写指针
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值