Linux fork 소개

프로 세 스 제어
프로 세 스 마다 마이너스 정수 가 아 닌 유일한 프로 세 스 ID 가 있 습 니 다. 유일 하지만 재 활용 할 수 있 습 니 다. 그러나 즉시 재 활용 하 는 것 이 아니 라 지연 알고리즘 을 사용 하여 같은 ID 를 사용 한 이전 프로 세 스 로 잘못 생각 하지 않도록 합 니 다.
특수 프로 세 스:
ID 가 0 인 것 은 스케줄 러 프로 세 스 입 니 다. 이 프로 세 스 는 커 널 의 일부분 입 니 다. 디스크 에 있 는 프로그램 ID 가 1 인 것 은 Init 프로 세 스 입 니 다. init 는 시스템 과 관련 된 초기 화 파일 (/ etc / rc * 파일, / etc / inittab 파일, / etc / init. d / 에 있 는 파일) ID 가 2 인 것 은 페이지 보호 프로 세 스 입 니 다. 가상 메모리 시스템 의 페이지 작업 을 지원 합 니 다.
프로 세 스 ID 를 제외 하고 프로 세 스 마다 다른 식별 자가 있 습 니 다.
#include 
pid_t getpid(void);//         ID
pid_t getppid(void);//        ID
uid_t getuid(void);//         ID
uid_geteuid(void);//         ID
gid_t getgid(void);//        ID
gid_t getegid(void);//        ID

fork 호출
#include 
pid_t fork(void);
//     0
//        ID
//    -1
fork 함수 가 한 번 호출 되면 두 번, 하위 프로 세 스에 서 0 을, 부모 프로 세 스에 서 하위 프로 세 스 의 ID 를 되 돌려 줍 니 다.하위 프로 세 스 가 부모 프로 세 스 의 데이터 공간, 쌓 기, 스 택 복사 본 을 가 져 옵 니 다.
#include 
#include 
#include 
#include 
#include 
#include 

int globvar=6;//    
char buf[]="hello world\r
"
; int main(void ) { int var;// pid_t pid; var = 88; int *ptr=(int *)malloc(sizeof(int)); *ptr=2; if(write(STDOUT_FILENO,buf,sizeof(buf)-1)!=sizeof(buf)-1) { printf("write error\r
"
); return -1; } printf("before fork\r
"
); if((pid=fork())<0) { printf("fork error"); return -1; } else if(pid==0)//child { ++*ptr; ++var; ++globvar; } else//parent { sleep(2); } printf("pid = %ld, globvar = %d, &var = %ld , var = %d , *ptr = %d , ptr=%ld\r
"
,(long)getpid(),globvar,(long)&var, var ,*ptr,(long)ptr); free(ptr); return 0; }

직접 실행:
./fork

인쇄 결과:
hello world
before fork
pid = 16722, globvar = 7, &var = 140722924809824 , var = 89 , *ptr = 3 , ptr=22728720
pid = 16721, globvar = 6, &var = 140722924809824 , var = 88 , *ptr = 2 , ptr=22728720

우 리 는 주소 가 모두 같 지만 값 이 다르다 는 것 을 보 았 습 니 다. 하위 프로 세 스 에서 복사 가 발생 했 음 을 설명 합 니 다. 그런데 왜 주소 가 같 습 니까?
물리 적 주소 와 논리 적 주소 (또는 가상 주소) 의 개념 과 관련된다.
운영 체제 에서 논리 적 주소 가 물리 적 주소 로 바 뀌 는 과정 을 주소 재 정립 이 라 고 한다.
나 누 기:
정적 재 포 지 셔 닝 - 프로그램 이 메 인 저장 소 를 불 러 올 때 논리 주 소 를 물리 적 주소 와 변환 을 완 료 했 습 니 다. 프로그램 이 실행 되 는 동안 변 하지 않 습 니 다.동적 재 포 지 셔 닝 – 프로그램 실행 기간 이 완료 되 었 습 니 다. 기본 주소 레지스터 와 같은 하드웨어 주소 변환 기구 에 의존 합 니 다.
논리 주소:
컴퓨터 시스템 구조 에 서 는 응용 프로그램 각도 에서 보 이 는 메모리 셀 (memory cell), 저장 장치 (storage element), 네트워크 호스트 (network host) 의 주 소 를 말한다.논리 주 소 는 물리 적 주소 (physical address) 와 다 르 기 때문에 주소 번역기 (address translator) 나 매 핑 함 수 를 통 해 논리 주 소 를 물리 적 주소 로 바 꿀 수 있다.
물리 주소:
물리 적 주소 (영어: physical address) 는 실제 주소 (real address), 바 이 너 리 주소 (binary address) 라 고도 부 릅 니 다. 주소 버스 에 전자 형식 으로 존재 하여 데이터 버스 가 메 인 저장 소의 특정한 저장 장치 의 메모리 주 소 를 방문 할 수 있 도록 합 니 다.가상 메모리 와 의 컴퓨터 에서 물리 적 주소 라 는 용 어 는 주로 가상 주 소 를 구분 하 는 데 쓰 인 다.특히 메모리 관리 장치 (MMU) 를 사용 하여 메모리 주 소 를 변환 하 는 컴퓨터 에 서 는 가상 과 물리 주 소 는 각각 MMU 를 통 해 변환 되 기 전과 그 후의 주 소 를 가리킨다.
인터넷 에서 물리 적 주소, 논리 적 주 소 를 잘 소개 하 는 블 로 그 를 보 았 다.http://www.cppblog.com/fwxjj/archive/2009/05/27/85897.html
물리 적 주소 와 논리 적 주 소 를 알 고 상술 한 문 제 를 보십시오.
fork 이후 exec 이전 두 프로 세 스 는 같은 물리 공간 (메모리 구역) 을 사 용 했 습 니 다. 하위 프로 세 스 의 코드 세그먼트, 데이터 세그먼트, 스 택 은 모두 부모 프로 세 스 를 가리 키 는 물리 공간 입 니 다. 즉, 이들 의 가상 공간 은 다 르 지만 해당 하 는 물리 공간 은 같 습 니 다.
부자 프로 세 스 에서 해당 세그먼트 를 변경 하 는 행위 가 발생 했 을 때 하위 프로 세 스 에 해당 하 는 세그먼트 에 물리 적 공간 을 분배 합 니 다. exec 때 문 이 아니라면 커 널 은 하위 프로 세 스 의 데이터 세그먼트, 스 택 세그먼트 에 해당 하 는 물리 적 공간 을 분배 합 니 다. (이로써 이들 은 각자 의 프로 세 스 공간 이 있 고 서로 영향 을 주지 않 습 니 다) 코드 세그먼트 는 부모 프로 세 스 의 물리 적 공간 을 계속 공유 합 니 다. (이들 의 코드 는 완전히 같 습 니 다)。 만약 에 exec 때 문 이 라면 이들 이 실행 하 는 코드 가 다 르 기 때문에 서브 프로 세 스 의 코드 세그먼트 도 단독 물리 공간 을 분배 합 니 다.
포크 이후 커 널 은 하위 프로 세 스 를 대기 열 앞 에 두 고 부모 프로 세 스 가 실 행 될 때 복사 되 지 않도록 하위 프로 세 스 를 먼저 실행 합 니 다. 이후 하위 프로 세 스 는 exec 시스템 호출 을 실행 하여 무의미 한 복사 로 인해 효율 이 떨 어 집 니 다.
fork 시 하위 프로 세 스 는 부모 프로 세 스 데이터 공간, 더미, 스 택 의 복 사 를 받 기 때문에 변수의 주소 (물론 가상 주소) 도 마찬가지 입 니 다.
모든 프로 세 스 는 자신의 가상 주소 공간 을 가지 고 있 으 며, 서로 다른 프로 세 스 의 같은 가상 주 소 는 분명히 서로 다른 물리 적 주소 에 대응 할 수 있다.따라서 주소 가 같 고 값 이 다 르 면 이상 하지 않다.
구체 적 인 과정 은 다음 과 같 습 니 다. fork 서브 프로 세 스 는 부모 프로 세 스 의 스 택 공간 을 완전히 복사 하고 페이지 도 복 사 했 지만 물리 페이지 를 복사 하지 않 았 습 니 다. 그래서 이 때 가상 주소 가 같 고 물리 적 주소 도 같 습 니 다.
그러나 부자 가 공유 하 는 페이지 를 '읽 기 전용' 으로 표시 합 니 다.
이 프로 세 스 가 공 유 된 페이지 에 대해 '쓰기 작업' 을 할 때 까지 커 널 은 물리 적 페이지 를 복사 하여 이 프로 세 스에 사용 하고 페이지 표를 수정 합 니 다.
원래 읽 기 전용 페이지 를 '쓸 수 있 음' 으로 표시 하고 다른 프로 세 스에 남 겨 두 는 것 이 이른바 '쓸 때 복사' 입 니 다.
참고:http://www.cnblogs.com/zhangchaoyang/articles/2317420.html
위 코드 가 실행 되면:
./fork > see.txt

see. txt 파일 을 열 고 출력 은:
hello world
before fork
pid = 14001, globvar = 7, &var = 140725591119472 , var = 89 , *ptr = 3 
before fork
pid = 14000, globvar = 6, &var = 140725591119472 , var = 88 , *ptr = 2 

하나 더 인쇄 했 어 요 before fork. 이게 무슨 이유 예요?
우선, stdin 과 stdout 은 모두 줄 버퍼 입 니 다. 즉,
가 flush 버퍼 를 만 났 기 때문에 이전 에 직접 실행 ./fork 할 때 하나만 인쇄 합 니 다 before fork.
버퍼 가 새로 고침 되 었 기 때 문 입 니 다.
그러나 파일 을 바 꿀 때 표준 출력 이 전체 버퍼 로 바 뀌 었 기 때문에 하위 프로 세 스 는 버퍼 를 복사 합 니 다.
한 마디 로 설명 하 다.
터미널 을 위 한 버퍼 링 은 대화 식 장 치 를 가리 키 지 않 을 때 전체 버퍼 링 입 니 다.
따라서 하위 프로 세 스 는 부모 프로 세 스 의 버퍼 를 복사 합 니 다.
참고:http://blog.csdn.net/zhangxiao93/article/details/70666125

좋은 웹페이지 즐겨찾기