tft每日頭條

 > 圖文

 > drools從入門到精通

drools從入門到精通

圖文 更新时间:2025-02-12 03:43:35

應評論要求,今天發一篇swoole的文章。如果感覺有幫助,記得點個贊,轉發分享評論。

進程隔離

官網上有那麼一句話:

進程隔離也是很多新手經常遇到的問題。修改了全局變量的值,為什麼不生效,原因就是全局變量在不同的進程,内存空間是隔離的,所以無效。

如果小夥伴們之前對進程沒有概念,要理解起來還是有一定難度的。所以在這裡,我有必要說一下進程是什麼東西。

簡單來說,進程是一個數據結構,數據結構裡面存放了很多成員變量,這個是最本質的。很多書說:

進程是資源的集合

那麼這句話所說的資源指的就是這些變量存放的東西,集合指的就是進程這個數據結構。

如果還是有一些抽象,不要緊,我們去看看Linux中進程這個數據結構的定義是怎樣的。數據結構的定義在這裡,大概是在593行的位置:

我列舉幾個這個數據結構裡面我們聽的比較多的成員變量:

struct task_struct {

操作系統會為每一個進程分配一個task_struct數據結構,一旦CPU執行某個進程的代碼的時候,操作系統把當前進程的這些變量提供給CPU。因為每個進程都有自己的這個task_struct數據結構,所以每個進程的變量是在各自的進程裡面的,因此不同進程的變量是隔離的,這些變量也包括全局變量、文件句柄(即上圖中的fd)。

緊接着,官網又給出那麼一句話:

不同進程的文件句柄是隔離的,所以在A進程創建的Socket連接或打開的文件,在B進程内是無效,即使是将它的fd發送到B進程也是不可用的

這句話什麼意思呢?為了搞清楚,我們要知道文件句柄的作用。

當用戶調用open系統調用(或者其他打開文件的系統調用)的時候,内核會創建一個打開文件對象來表示該文件的一個打開實例。内核同時也會分配一個文件描述符(也就是上圖中的fd)作為打開文件對象的句柄。如下圖所示:

drools從入門到精通(看了這篇文章你就懂了)1

open系統調用向進程返回這個文件描述符,然後這個文件描述符就被存放在file array裡面了。然後進程就可以通過這個fd1來找到對應的文件。那麼,圖中的offset是什麼意思呢(我們把offset叫做打開文件對象)?在Unix系統中,文件默認是順序訪問的。當用戶打開文件的時候,内核初始化這個offset的偏移指針為0。舉個例子,如果當前進程剛打開一個文件(文件内容是字符串abcdefghijklnm),那麼此時offset的狀态如下:

drools從入門到精通(看了這篇文章你就懂了)2

因為offset的偏移指針為0,所以指向字母a。所以,當我們通過fd去讀取文件内容的時候,讀取到的第一個字符就是字母a。假設我連續讀了3個字節,那麼此時的狀态應該是這個樣子的:

drools從入門到精通(看了這篇文章你就懂了)3

也就是說,當進程從文件裡面讀取3個字節之後,offset此時指向字母d。當進程下一次讀取文件的時候,讀取出來的第一個字母就是d了。這就是offset的概念。

同一個進程還可以多次打開同一個文件,如下圖所示:

drools從入門到精通(看了這篇文章你就懂了)4

可以看出,雖然fd1和fd2都是指向同一個文件,但是,如果進程通過fd1去讀取文件的話,讀到的第一個字母是d;如果進程通過fd2去讀取文件的話,讀取到的第一個字母是a。所以,每個文件描述符代表着與文件的一個獨立會話,對應的打開文件對象(即圖中的offset)保存者該會話的内容,這包括了被打開文件的模式(隻讀、隻寫、讀寫)以及下一次讀取或者寫入時的偏移指針。

我們通過代碼來直觀感受一下:

$handle1 = fopen("file.txt", "r");

$handle2 = fopen("file.txt", "r");

$content = fread ($handle1 , 3);

echo "The process reads three bytes through handle1, the content is: " . $content . PHP_EOL;

$content1 = fread ($handle1 , 1);

$content2 = fread ($handle2 , 1);

echo "The process reads one bytes through handle1, the content is: " . $content1 . PHP_EOL;

echo "The process reads one bytes through handle2, the content is: " . $content2 . PHP_EOL;

結果如下:

drools從入門到精通(看了這篇文章你就懂了)5

驗證了我們的說法。

正是因為offset這個打開文件對象對同一個文件的不同會話進行了隔離,所以,才有了官網的這句話:

不同進程的文件句柄是隔離的,所以在A進程創建的Socket連接或打開的文件,在B進程内是無效,即使是将它的fd發送到B進程也是不可用的

也就是說,就算fd是一樣的,但是offset是不一樣的。

其實到這裡算是講完了隔離,但是,我還想再講一點其他的東西。

即,同一個進程是否可以讓多個fd指向同一個offset,從而達到多個fd共享同一個offset的效果呢?答案是可以做到。

進程可以通過dup系統調用來複制一個文件描述符fd,這樣一來,兩個文件描述符共享着相同的會話:

drools從入門到精通(看了這篇文章你就懂了)6

代碼如下:

$handle1 = fopen("file.txt", "r");

$handle2 = dup($handle1);

$content = fread ($handle1 , 3);

echo "The process reads three bytes through handle1, the content is: " . $content . PHP_EOL;

$content1 = fread ($handle1 , 1);

$content2 = fread ($handle2 , 1);

echo "The process reads one bytes through handle1, the content is: " . $content1 . PHP_EOL;

echo "The process reads one bytes through handle2, the content is: " . $content2 . PHP_EOL;

(注意,這段代碼運行不了,因為PHP沒有提供dup這個函數)

假設,這個函數是可以運行,那麼輸出的結果應該是

The process reads three bytes through handle1, the content is: abc

The process reads one bytes through handle1, the content is: d

The process reads one bytes through handle2, the content is: e

drools從入門到精通(看了這篇文章你就懂了)7

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关圖文资讯推荐

热门圖文资讯推荐

网友关注

Copyright 2023-2025 - www.tftnews.com All Rights Reserved