分析下述程序,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結構體中的文件描述符:
文件描述符是非負整數。打開現存文件或新建文件時,內核會返回一個文件描述符。讀寫文件也需要使用文件描述符來指定待讀寫的文件。