分析下述程序,i<4时,最终创建了多少个进程。
fork()是创建一个子进程。
分析:i=0时,父进程1创建了一个子进程1。(此时共2个进程)
i=1时,父进程1继续创建子进程2,将子进程1又当成父进程,创建子进程3。(此时共6个进程)
i=2时,将子进程当成父进程继续创建子进程。之前的父进程继续创建子进程。(此时共14个进程)
i=3时,将子进程继续当成父进程继续创建子进程。之前的父进程继续创建子进程。(此时共30个进程)
注:可先计算由父进程创建的进程数,最后乘2即为总进程数。
扩展:当i<10时,一共创建了2046个进程。
2. 分析为什么在vfork()创建一个子进程中,在子进程中不能用return。
注:从结果可以看出:子进程先运行。在它调用exec或exit之后父进程才可能被调度运行。
若将程序中的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():保证子进程先运行,在调用exec或exit之前与父进程数据是共享的,在它调用exec或exit之 后父进程才可能被调度运行。
3. file结构体
struct file结构体在include/linux/fs.h中定义。文件结构体代表一个打开的文件,系统中的每个打开的文件在内核空间都有一个关联的 struct file。它由内核在打开文件时创建,并传递给在文件上进行操作的任何函数。在文件的所有实例都关闭后,内核释放这个数据结构。在内核创建和驱动源码中,struct file的指针通常被命名为file或filp。
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结构体中的文件描述符:
文件描述符是非负整数。打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件。
本文出自 “一起去看星星” 博客,转载请与作者联系!
原文地址:http://10810429.blog.51cto.com/10800429/1792398