>운영 및 유지보수 >리눅스 운영 및 유지 관리 >프로세스 환경 - 프로세스 관리

프로세스 환경 - 프로세스 관리

巴扎黑
巴扎黑원래의
2017-07-23 11:16:271699검색

프로그램이 실행될 때 메인 함수가 어떻게 호출되는지, 명령줄 매개변수가 프로그램에 어떻게 전달되는지, 일반적인 저장 공간 레이아웃은 어떤지, 다른 저장 공간은 어떻게 할당하는지, 프로세스가 환경 변수를 사용하는 방법, 종료 프로세스 등. 이는 모두 프로세스 제어에 대한 기본 지식입니다.


프로세스 시작 및 종료

커널은 c 프로그램을 실행할 때 exec 함수를 사용하여 커널에서 명령줄 매개변수와 환경 변수 값을 얻는 특수 시작 루틴을 호출합니다.

프로세스 종료 상황

5가지 정상적인 종료 상황:

(1)从main函数返回;
(2)调用exit;
(3)调用_exit和_Exit函数;
(4)最后一个线程调用pthread_exit;
(5)最后一个线程从其启动例程返回;

3가지 비정상적인 종료 상황

(1)调用abort;
(2)接到一个信号;
(3)最后一个线程对取消请求做出响应;

프로세스 시작 및 종료 다이어그램

프로세스 환경 - 프로세스 관리

atexit 기능

프로세스는 최대 32가지 기능(예: :signal 기능)을 등록할 수 있습니다. ), 이러한 함수는 종료 함수에 의해 자동으로 호출됩니다. 이러한 함수는 프로그램이 종료될 때 호출되어 프로세스를 종료하기 전에 마무리 작업을 수행하는 종료 핸들러를 구성합니다. 종료 함수는 atexit 함수의 등록 기록을 사용하여 호출할 함수를 결정합니다.

exit 함수

이 함수는 ISO C에 의해 정의되며 해당 작업에는 종료 핸들러 처리 및 모든 표준 I/O 스트림 닫기가 포함됩니다. 파일 설명자, 다중 프로세스(상위-하위 프로세스) 및 작업 제어를 처리하지 않는다는 점에 유의해야 합니다.

_e(E)xit 함수
ISO C 이 함수를 정의하는 목적은 프로세스가 종료 핸들러나 신호 처리 함수를 실행하지 않고 프로그램을 종료할 수 있는 방법을 제공하는 것입니다. 그러나 ISO C가 표준 I/O 스트림을 플러시하는지 여부는 운영 체제 구현에 따라 다릅니다. 유닉스에서는 플러시가 수행되지 않습니다.

종료 및 _e(E)ixt 함수의 상태 코드

프로세스가 어떻게 종료되든 커널에서 동일한 코드를 실행합니다(프로세스 시작 및 종료 다이어그램에서 볼 수 있듯이). 이 코드는 모든 파일 설명자를 닫고 모든 저장 공간을 해제합니다.

프로그램 종료 후 종료 코드를 사용하여 상위 프로세스에 해당 프로세스를 알립니다. 상위 프로세스는 wait 또는 waitpid 함수를 사용하여 하위 프로세스의 여파를 완료합니다(자식 프로세스에 대한 정보를 얻고 하위 프로세스가 점유한 리소스를 해제합니다). 상위 프로세스가 하위 프로세스의 종료 상태를 처리하지 않으면 하위 프로세스는 좀비 프로세스가 됩니다. 반대로 상위 프로세스가 하위 프로세스보다 먼저 종료되면 하위 프로세스는 고아 프로세스가 됩니다. 고아 프로세스는 프로세스 1번(init 프로세스)에 의해 수신됩니다. 일반적인 프로세스는 다음과 같습니다:

(1)进程终止时,内核逐个检查所有活动的进程;
(2)分析查找该终止进程的子进程;
(3)将该进程的子进程的父进程ID改为1;

wait 및 waitpid 함수

프로그램이 정상적으로 또는 비정상적으로 종료되면 커널은 부모에게 SIGNAL 신호를 보냅니다. 프로세스. 자식 프로세스의 종료는 비동기 이벤트이므로 이 신호도 비동기 신호입니다. 이 신호는 일반적으로 기본적으로 상위 프로세스에서 무시됩니다. 또는 그 여파에 대처할 수 있는 신호 처리 기능을 제공하십시오. wait 및 waitpid 기능은 신호 처리 기능의 일부입니다.

wait와 waitpid 함수의 차이점은 다음과 같습니다.

(1)wait会阻塞调用者进程等待直至第一个终止的子进程到来;
(2)waitpid可以通过参数设置,来实现调用者进程不阻塞,或选择要阻
塞等待的子进程;

여기서 호출자는 상위 프로세스를 나타냅니다.

환경 테이블 및 환경 변수

환경 테이블 구조 다이어그램

프로세스 환경 - 프로세스 관리

  • 모든 프로그램은 환경 테이블

  • 환경 테이블은 문자 포인터의 배열이기도 합니다

  • enrivon은 환경 포인터라고 합니다

  • 포인터의 배열을 환경 테이블이라고 합니다

  • 각 포인터가 가리키는 문자열 을 환경 문자열이라고 합니다

환경 변수

  • unix 커널은 환경 문자열을 확인하지 않으며 해석은 전적으로 각 응용 프로그램 프로세스에 따라 달라집니다.

  • 일반적으로 환경 변수는 셸 시작 파일에 설정되어 작업을 제어합니다. the shell

  • 환경 수정 또는 추가 변수를 사용하면 현재 프로세스와 생성 및 호출된 후속 하위 프로세스(이전 프로세스는 제외)의 환경에만 영향을 미칠 수 있지만, 환경에는 영향을 줄 수 없습니다. 해당 상위 프로세스

환경 변수와 관련된 함수는 다음과 같습니다.

#include<stdlib.h>
char *getenv(const char *name);
      返回值:指向与name关联的value的指针;若未找到,返回NULL

int putenv(char *str);
                       返回值:若成功,返回0;若出错,返回非0
                       
int setenv(const char *name, const char *value,
            int rewrite);
int unsetenv(const char *name);
                两个函数返回值:若成功,返回0;若出错,返回-1</stdlib.h>

이 함수가 환경 테이블을 어떻게 수정합니까? 환경 테이블과 환경 문자열은 일반적으로 메모리 공간의 상위 주소(상위)에 저장됩니다. 따라서 해당 값을 수정하면 메모리가 상위 주소로 계속 확장될 수 없지만 그 아래에 스택 프레임이 있으므로 아래쪽으로 확장할 수 없습니다. 해당 값을 수정하는 과정은 다음과 같습니다.

(1) 환경 테이블 수정

1)新value = 旧value,调用malloc函数,在堆区开辟新的存储空间,
将新value复制到这里,再将这片存储区首地址写到环境表相应的位置处。

(2) 환경 테이블 추가

1)新增一个环境变量,调用malloc函数开辟新的存储空间,将原来的环
境表复制到该存储区,其次再添加一个环境变量,然后在尾部赋值为NULL,
最后将environ指向该区域;
2)在 1)过程的基础上,调用realloc函数,多次添加环境变量;

참고:

이 방법으로 수정된 환경 변수는 현재 프로그램에서는 런타임 동안 유효하며, 해당 저장 영역은 시스템에 의해 재활용되며 이러한 수정 사항은 무효화됩니다. 메모리 저장 구조에 대한 보충 설명

메모리 관리 구조 다이어그램

프로세스 환경 - 프로세스 관리

  • 초기화되지 않은 데이터 세그먼트(기호로 시작되는 블록):

    프로그램이 실행되기 전에 커널은 이 세그먼트의 데이터를 0으로 초기화합니다. 또는 널 포인터;

  • 스택:

    함수가 호출될 때마다 함수의 반환 주소와 호출자의 환경 정보(예: 일부 머신 레지스터 값)가 스택에 저장됩니다.

  • 共享库:只需在所有进程都可引用的存储区中保存这种库例程的一个副本;

存储空间分配函数

#include<stdlib.h>
void *malloc(size_t size);
void *calloc(size_t nojy, size_t size);
void *realloc(void *ptr, size_t newsize);
         3个函数返回值:若成功,返回非空指针;若出错,返回NULL</stdlib.h>
  • malloc函数:初始值不确定;底层通过调用sbrk函数实现;

  • calloc函数:初始值为0;

  • realloc函数:增加或减少以前分配区的长度;当增加长度时,可能将以前分配区的内容移到另一个足够大的区域,以便在分配区末尾增加存储区,而新增存储区初始值不确定(例如:可变数组的使用);

注意:这些动态分配的函数一般在分配存储空间时,会比要求的大。因为在开辟空间的前后部分存储记录管理信息。因此,在使用时,千万不要越界访问,以免造成不可预知的后果。

函数间跳转策略

在c语言中,goto语句是不能跨函数跳转的。尤其是在函数深层调用时的跳转需求,在出错处理的情况下非常有用。

#include<setjmp.h>
int setjmp(jmp_buf env);
          返回值:若直接调用,返回0;若从longjmp返回,返回非0
void longjmp(jmp_buf env, int val);</setjmp.h>

变量值回滚问题:自动变量和寄存器变量会存在回滚现象。利用volatile属性来避免此类情况的发生。(在给变量赋值时,赋的值回首先存储在内存(存储器变量)中,然后在由cpu取走,存储在cpu的寄存器上(寄存器变量)。在做系统优化时,那些频繁使用的变量,会直接存储到寄存器中而不经过内存。)

寄存器变量会存在回滚现象的探究

在调用setjmp函数时,内核会把当前的栈顶指针保存在env变量中,所以在调用longjmp函数返回该位置时,全局变量、静态变量、易失变量和自动变量如果在调用setjmp和longjmp函数之间它们的值被修改过,是不会回滚到setjmp函数调用之前的值(当然,编译器将auto变量优化为寄存器变量除外)。因为,这些存储器变量的值是存储在内存相应的段中,回到原先栈顶状态时,同样访问的还是原先的内存空间。

然而,对于寄存器变量来说,首先要明确一点:寄存器变量是用动态存储的方式。意思是寄存器变量的值可能存在不同的寄存器中。如果在调setjmp和longjmp函数之间它们的值被修改过,这个值可能不会存到setjmp之前的对其赋值的寄存器中,而在调用longjmp函数后,又回到了调用setjmp函数时的状态。这个时候再读取寄存器变量的值时,读到的是原先那个寄存器中存储的值而不是修改过的那个寄存器中存储的值,所以出现的回滚现象。

위 내용은 프로세스 환경 - 프로세스 관리의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.