日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

c语言 子进程,子Shell和子进程

發布時間:2023/12/10 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c语言 子进程,子Shell和子进程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Shell 中有很多方法產生子進程,比如以新進程的方式運行 Shell 腳本,使用組命令、管道、命令替換等,但是這些子進程是有區別的。

子進程的概念是由父進程的概念引申而來的。在 Linux 系統中,系統運行的應用程序幾乎都是從 init(pid為 1 的進程)進程派生而來的,所有這些應用程序都可以視為 init 進程的子進程,而 init 則為它們的父進程。

使用pstree -p命令就可以看到 init 及系統中其他進程的進程樹信息(包括 pid):

systemd(1)─┬─ModemManager(796)─┬─{ModemManager}(821)

│ └─{ModemManager}(882)

├─NetworkManager(975)─┬─{NetworkManager}(1061)

│ └─{NetworkManager}(1077)

├─abrt-watch-log(774)

├─abrt-watch-log(776)

├─abrtd(773)

├─accounts-daemon(806)─┬─{accounts-daemon}(839)

│ └─{accounts-daemon}(883)

├─alsactl(768)

├─at-spi-bus-laun(1954)─┬─dbus-daemon(1958)───{dbus-daemon}(1960)

│ ├─{at-spi-bus-laun}(1955)

│ ├─{at-spi-bus-laun}(1957)

│ └─{at-spi-bus-laun}(1959)

├─at-spi2-registr(1962)───{at-spi2-registr}(1965)

├─atd(842)

├─auditd(739)─┬─audispd(753)─┬─sedispatch(757)

│ │ └─{audispd}(759)

│ └─{auditd}(752)

本教程基于 CentOS 7 編寫,CentOS 7 為了提高啟動速度使用?systemd 替代了 init。CentOS 7 之前的版本依然使用 init。

Shell 腳本是從上至下、從左至右依次執行的,即執行完一個命令之后再執行下一個。如果在 Shell 腳本中遇到子腳本(即腳本嵌套,但是必須以新進程的方式運行)或者外部命令,就會向系統內核申請創建一個新的進程,以便在該進程中執行子腳本或者外部命令,這個新的進程就是子進程。子進程執行完畢后才能回到父進程,才能繼續執行父腳本中后續的命令及語句。

子進程的創建

了解 Linux 編程的讀者應該知道,使用 fork() 函數可以創建一個子進程;除了 PID(進程ID)等極少的參數不同外,子進程的一切都來自父進程,包括代碼、數據、堆棧、打開的文件等,就連代碼的執行位置(狀態)都是一樣的。

也就是說,fork() 克隆了一個一模一樣的自己,身高、體重、顏值、嗓音、年齡等各種屬性都相同。當然,后期隨著各自的發展軌跡不同,兩者會變得不一樣,比如 A 好吃懶做越來越肥,B 經常健身成了一個肌肉男;但是在 fork() 出來的那一刻,兩者都是一樣的。

Linux 還有一種創建子進程的方式,就是子進程被 fork() 出來以后立即調用 exec() 函數加載新的可執行文件,而不使用從父進程繼承來的一切。什么意思呢?

比如在 ~/bin 目錄下有兩個可執行文件分別叫 a.out 和 b.out。現在我運行 a.out,就會產生一個進程,比如叫做 A。在進程 A 中我又調用 fork() 函數創建了一個進程 B,那么 B 就是 A 的子進程,此時它們是一模一樣的。但是,我調用 fork() 后立即又調用 exec() 去加載 b.out,這可就壞事了,B 進程中的一切(包括代碼、數據、堆棧等)都會被銷毀,然后再根據 b.out 重建建立一切。這樣一折騰,B 進程除了 ID 沒有變,其它的都變了,再也沒有屬于 A 的東西了。

你看,同樣是創建子進程,但是結果卻大相徑庭:

第一種只使用 fork() 函數,子進程和父進程幾乎是一模一樣的,父進程中的函數、變量、別名等在子進程中仍然有效。

第二種使用 fork() 和 exec() 函數,子進程和父進程之間除了硬生生地維持一種“父子關系”外,再也沒有任何聯系了,它們就是兩個完全不同的程序。

對于 Shell 來說,以新進程的方式運行腳本文件,比如bash ./test.sh、chmod +x ./test.sh; ./test.sh,或者在當前 Shell 中使用 bash 命令啟動新的 Shell,它們都屬于第二種創建子進程的方式,所以子進程除了能繼承父進程的環境變量外,基本上也不能使用父進程的什么東西了,比如,父進程的全局變量、局部變量、文件描述符、別名等在子進程中都無效。

但是,組命令、命令替換、管道這幾種語法都使用第一種方式創建進程,所以子進程可以使用父進程的一切,包括全局變量、局部變量、別名等。我們將這種子進程稱為子 Shell(sub shell)。

子 Shell 雖然能使用父 Shell 的的一切,但是如果子 Shell 對數據做了修改,比如修改了全局變量,那么這種修改只能停留在子 Shell,無法傳遞給父 Shell。不管是子進程還是子 Shell,都是“傳子不傳父”。

總結

子 Shell 才是真正繼承了父進程的一切,這才像“一個模子刻出來的”;普通子進程和父進程是完全不同的兩個程序,只是維持著父子關系而已。

總結

以上是生活随笔為你收集整理的c语言 子进程,子Shell和子进程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。