Linux fork操作之后發生了什么?又會共享什么呢?


  今天我在閱讀《Unix網絡編程》時候遇到一個問題:accept返回時的connfd,是父子進程之間共享的?我當時很不理解,難道打開的文件描述符不是應該在父子進程間相互獨立的嗎?為什么是共享的呢?fork之后父子進程之間共享了什么?堆上的變量是否也共享了呢?

  做了如下的代碼測試,在fork之前先創建一個文件,在子進程中寫入字符串“shenlei”,父進程讀取文件內容,發現也是“shenlei”。說明打開的文件描述符在父子進程之間是共享的。另一方面,在父子進程中讀取文件描述符fd,發現二者相等,進一步證實了這個觀點。

  看來在《Unix網絡編程》中說的是對的,當close一個文件描述符時候會將文件描述符的引用計數-1。在普通文件io操作時,只有當引用計數為0才能真正關閉該文件描述符;在socket操作時,也只有當引用計數為0時才會發送FIN,四次揮手關閉相應的socket。

 

#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <iostream>

using namespace std;
static int global_val = 0;
int main()
{
	int *p = (int*)malloc(sizeof(int));
	*p=0;	
	int m = 2;
	pid_t pid ;
	int fd = open("mytest", O_RDWR | O_CREAT, 0666);
	if ((pid = fork()) < 0)
	{
		cout << "fork error" << endl;
	}
	else {
		if (pid == 0)
	{
		char buf[20]="\0";
		int res = read(fd,buf,20);
		cout<<"pid is "<<getpid()<<" res is "<<res<<" fd is "<<fd<<" buf is "<< buf<<endl;
		close(fd);
		//sleep(1);
		char bufs[8]="shenlei";
		lseek(fd, 0, SEEK_SET);		
		write(fd,bufs,strlen(bufs));
		global_val++;
		m++;
		(*p)++;
	}
		else{
		sleep(1);
		char buf[20]="\0";
		lseek(fd, 0, SEEK_SET);
		int res = read(fd,buf,20);
		cout<<"pid is "<<getpid()<<" res is "<<res<<" fd is "<<fd<<" buf is "<< buf<<endl;
		cout << *p << " " << m << " " << global_val<< endl;	
		}
	}
	return 0;
}

  然后又測試了下,一個進程中的堆對象能否共享,如上述代碼所示,結論是不可以的。全局變量,靜態變量,全局靜態變量也都是不行的。說明在fork創建多進程之后堆棧信息會完全復制給子進程內存空間,父子進程相互獨立。

某公司筆試題:當父進程調用fork()創建子進程之后,下列哪些變量在子進程中修改之后,父進程里也會相應地作出改動?

A.全局變量
B.局部變量
C.靜態變量
D.文件指針

看懂了以上的分析就很簡單了,答案是D。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM