1. 分析下述程序,i<4时,最终创建了多少个进程。

    fork()是创建一个子进程。

wKioL1dr8FnyJVySAAA0rxzoUSc801.png

 分析:i=0时,父进程1创建了一个子进程1。(此时共2个进程)

       i=1时,父进程1继续创建子进程2,将子进程1又当成父进程,创建子进程3。(此时共6个进程)

       i=2时,将子进程当成父进程继续创建子进程。之前的父进程继续创建子进程。(此时共14个进程)

       i=3时,将子进程继续当成父进程继续创建子进程。之前的父进程继续创建子进程。(此时共30个进程)


wKioL1dr9uiC8Tl4AAAYowWUwf4718.png

注:可先计算由父进程创建的进程数,最后乘2即为总进程数。

扩展:当i<10时,一共创建了2046个进程。


2. 分析为什么在vfork()创建一个子进程中,在子进程中不能用return。

   

wKioL1dsAdTBTeSlAAA4E_rKcvE421.png

wKiom1dsAdjR3GZ5AAAQV-7j6pU664.png

注:从结果可以看出:子进程先运行。在它调用execexit之后父进程才可能被调度运行。


  若将程序中的exit(0)改为return 0;将会出现错误。这是为什么呢?

  首先,先来分析下exit()和return的区别

  exit() 是退出整个程序,将控制权交给操作系统。在执行了exit()后,所有的内存和临时存储区会被刷新,所有文件会被关闭,控制权不再在程序中。

  return 是从函数返回,并将控制权交给调用函数。如果在main()中,可直接return 0,退出当前进程。若不在main()函数中,则是退出上一层调用。

  下面就解释,为什么在vfork中不能用return

  vfork() 创建出来的子进程和父进程共享一个内存数据。子进程的main()函数 return掉了,将程序函数的栈发生了变化。当main()函数return后,会调用exit(),父进程收到子进程exit(),开始从vfork()返回,但是,父进程的栈被子进程给return掉了。栈返回一个栈地址,再次调用main(),进入了一个无限循环。


fork() 和 vfork() 的区别:

fork()和vfork()都是创建一个子进程。

区别:

(1)fork() :子进程拷贝父进程的数据段,代码段

     vfork() :子进程与父进程共享数据段

(2)fork() :父子进程的执行顺序不确定,有调度器决定

     vfork():保证子进程先运行,在调用execexit之前与父进程数据是共享的,在它调用execexit之                 后父进程才可能被调度运行。


3. FILE结构体

  struct file结构体在include/linux/fs.h中定义。文件结构体代表一个打开的文件,系统中的每个打开的文件在内核空间都有一个关联的 struct file。它由内核在打开文件时创建,并传递给在文件上进行操作的任何函数。在文件的所有实例都关闭后,内核释放这个数据结构。在内核创建和驱动源码中,struct file的指针通常被命名为filefilp

  FILE结构体:

  struct file {
  union {
  struct list_head fu_list; 文件对象链表指针linux/include/linux/list.h
  struct rcu_head fu_rcuhead; RCU(Read-Copy Update)是Linux 2.6内核中新的锁机制
  } f_u;
  struct path f_path; 包含dentry和mnt两个成员,用于确定文件路径
  #define f_dentry f_path.dentry f_path的成员之一,当前文件的dentry结构
  #define f_vfsmnt f_path.mnt 表示当前文件所在文件系统的挂载根目录
  const struct file_operations *f_op; 与该文件相关联的操作函数
  atomic_t f_count; 文件的引用计数(有多少进程打开该文件)
  unsigned int f_flags; 对应于open时指定的flag
  mode_t f_mode; 读写模式:open的mod_t mode参数
  off_t f_pos; 该文件在当前进程中的文件偏移量
  struct fown_struct f_owner; 该结构的作用是通过信号进行I/O时间通知的数据。
  unsigned int f_uid, f_gid; 文件所有者id,所有者组id
  struct file_ra_state f_ra; 在linux/include/linux/fs.h中定义,文件预读相关
  unsigned long f_version;
  #ifdef CONFIG_SECURITY
  void *f_security;
  #endif
  
  void *private_data;
  #ifdef CONFIG_EPOLL
  
  struct list_head f_ep_links;
  spinlock_t f_ep_lock;
  #endif
  struct address_space *f_mapping;
  };


FILE结构体中的文件描述符:

文件描述符是非负整数。打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件。