Linux中的fork函数

操作系统实验二

fork函数

作用

fork函数将运行着的程序分成2个(几乎)完全一样的进程,每个进程都启动一个从代码的同一位置开始执行的线程

返回值

  • 负值:创建子进程失败。
  • 零:返回到新创建的子进程。
  • 正值:返回父进程或调用者。该值包含新创建的子进程的进程ID
    image

用法

pid_t pid=fork();如果创建成功,会有两个进程:父进程和子进程,fork在这两个进程中分别返回,就是返回两次且返回值不同。

一段程序

# include<stdio.h>
# include<sys/types.h>
# include<unistd.h>

int main()
{ 
  int pid1, pid2;
  printf("I am father %d! My father is %d.\n", getpid(), getppid());
  if ((pid1 = fork())<0) //fork return value < 0 , create failed
  {
    printf("Child1 fail create!\n");
    return 1;
  }
  else if (pid1 == 0)  //fork return value = 0, son is running
  {
    printf("I am son %d! My father is %d. \n", getpid(), getppid());
    return 0;
  }
  if ((pid2 = fork())<0)
  {
    printf("Child2 fail create!\n");
    return 0;
  }
  else if (pid2 == 0)
  {
    printf("I am daughter %d! My father is %d.\n", getpid(), getppid());
    return 0;
  }
}

编译运行

gcc fork.c -o fork
./fork

运行结果
image
分析: 首先是父进程,打印了它的身份和进程号,还有它的父进程号
在第一个if语句中创建了子进程,子进程创建成功,返回值是0,执行第一个else if,打印身份是子进程和它的进程号和父进程号。
父进程的fork返回值是子进程号大于0,不满足第一个条件,顺序往下执行,在第二个if里创建了一个进程。
子进程创建成功,返回值是0,执行else if,打印身份、进程号和父进程号。
daughter进程的父进程号时884,是因为父进程已经运行结束了,daughter进程找不到原来的父进程,变成了孤儿进程,被其他进程收养了。
image
分析: 有时daughter进程和son进程顺序不一样是因为父进程比son进程执行的快,先创建了daughter进程,daughter进程先进行了打印。
打印在命令行上的原因:
处理父进程、son进程、daughter进程,还有一个shell进程,shell进程就是用户和linux交互的进程,用于解析输入的命令行。这四个进程都要抢占屏幕这个资源,如果被shell先抢占了,就会出现命令行,其他进程输出就会在命令行上了。(不知道理解的对不对。。。)

孤儿进程

父进程运行结束后,它创建的子进程还在运行,这些子进程就会成为孤儿进程。
避免出现孤儿进程: 在父进程运行最后加上sleep(1),父进程不会运行那么快,保证子进程先退出。
image

lockf函数

参考:https://blog.csdn.net/qq_24421591/article/details/49104455

用处

实现资源的互斥访问

例子

# include<stdio.h>
# include<sys/types.h>
# include<unistd.h>

int main(){
    int pid1, pid2;
    pid1=fork();
    if(pid1 == 0)
    {
        for(int i = 0; i < 5; i ++ )
        {
            lockf(1,1,0); 	//加锁
            printf("I am son %d\n",i);
            lockf(1,0,0); //解锁
            sleep(3); //等待3s
        }
    }
    else
    {
        pid2=fork();
        if(pid2 == 0)
        {
            for(int i = 0; i < 5; i ++ )
            {
                lockf(1,1,0);
                printf("I am daughter %d\n",i);
                lockf(1,0,0);
                sleep(3);
            }
        }
        else
        {
            printf("I am father\n");
        }
    }
	return 0;
}

image
分析: 临界资源是屏幕,son进程和daughter进程会交替打印,是因为在循环中打印过后,会等待3s,在等待的时间里,另一个进程就是抢占资源,进行打印。
对比
将sleep(1)放在解锁之前,这样即使进程在sleep,其他进程也没有机会抢占资源。
image

posted @ 2021-12-14 19:18  inss!w!  阅读(1741)  评论(0编辑  收藏  举报