linux_process 학습-ttyname 기능-getpgrp-getpgid-setpgid 기능-getsid-setsid 기능-데몬 프로세스-linux 세션

이전 기사에서 계속: linux_shared storage mapping area-mmap function-munmap function-process communication-strace command

  이번에는 ttyname함수, getpgrp함수, getpgid함수, setpgid함수, getsid함수, setsid함수, 데몬프로세스 등 프로세스 지식에 대해 더 많은 학습 내용을 공유할 예정입니다. 제공하려면:

이 블로거가 CSDN에 게시한 기사 카탈로그: [ 내 CSDN 카탈로그, CSDN에 블로거가 게시한 기사 유형에 대한 가이드 ]

1. ttyname 함수

함수 함수:
  파일 디스크립터에서 해당 파일 이름 찾기
헤더 파일:
  #include <unistd.h>
함수 프로토타입:
  char *ttyname(int fd),
함수 매개변수:
  fd: 파일 디스크립터
반환 값:
  성공: 터미널 이름,
  실패: NULL, 오류 번호 설정

  다음으로 ttyname 함수를 이용하여 다양한 단말에 해당하는 장치 파일명을 실험을 통해 알아본다.

#include <unistd.h>
#include <stdio.h>
int main(void)
{
    
    
    printf("fd 0: %s\n", ttyname(0));
    printf("fd 1: %s\n", ttyname(1));
    printf("fd 2: %s\n", ttyname(2));
    return 0;
}

2. 공정 그룹 운전 기능

2.1 getpgrp 함수

함수 함수:
  현재 프로세스의 프로세스 그룹 ID 가져오기
헤더 파일:
   #include <unistd.h>
함수 프로토타입:
  pid_t getpgrp(void)
함수 매개변수:
  없음
반환 값:
  호출자의 프로세스 그룹 ID를 반환합니다.

2.2 getpgid 함수

기능:
  지정된 프로세스의 프로세스 그룹 ID를 가져옵니다.
헤더 파일:
  #include <unistd.h>
함수 프로토타입:
  pid_t getpgid(pid_t pid),
함수 매개변수:
  pid: 프로세스 ID, pid = 0이면 함수는 getpgrp와 동일합니다.
반환 값:
  성공: 0,
  실패: -1, errno 설정

2.3 예제 - getpgrp 함수 - getpgid 함수

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{
    
    
    pid_t pid;

    if ((pid = fork()) < 0) 
	{
    
    
        perror("fork");
        exit(1);
    } 
	else if (pid == 0) {
    
    
        printf("当前子进程id == %d\n", getpid());    //子进程ID
        printf("当前子进程组-getpgrp-id ID == %d\n", getpgrp());    //子进程所在组ID,传0表当前进程
        printf("当前子进程组-getpgid-id ID == %d\n", getpgid(0));                   
        printf("当前子进程组-getpgid(getpid())- ID == %d\n", getpgid(getpid()));
        exit(0);
    }
    sleep(3);
    printf("父进程 ID == %d\n", getpid());
    printf("父进程组 ID == %d\n", getpgrp());
    return 0;
}

2.4 setpgid 함수

기능 역할:
  기본적으로 프로세스가 속한 프로세스 그룹을 변경합니다. 일반적으로 기존 프로세스 그룹에 가입하거나 새 프로세스 그룹을 만드는 데 사용됩니다.
헤더 파일:
  #include <unistd.h>
기능 프로토타입:
  int setpgid(pid_t pid, pid_t pgid);
기능 매개변수:
  pid: 프로세스 ID.
  pgid: 프로세스 그룹 ID.
    참조 1에 해당하는 프로세스가 참조 2에 해당하는 프로세스 그룹에 추가될 예정입니다.
반환 값:
  성공: 0,
  실패: -1, errno 설정

참고:
  1. 하위 프로세스가 새 그룹으로 변경되는 경우 포크 후 exec 이전이어야 합니다.
  2. 전력 수준의 문제. 루트가 아닌 프로세스는 자신이 만든 자식 프로세스 또는 작업 권한이 있는 프로세스만 변경할 수 있습니다.

2.5 예제 - setpgid 함수

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
    
    
    pid_t pid;

    if ((pid = fork()) < 0) 
	{
    
    
        perror("fork");
        exit(1);
    } 
	else if (pid == 0) {
    
    
        printf("子进程 ID == %d\n",getpid());
        printf("子进程组 ID == %d\n",getpgid(0)); // 返回组id
        //printf("child Group ID == %d\n",getpgrp()); // 返回组id
        sleep(5);
        printf("----子进程组ID被改变后的组 ID == %d\n",getpgid(0));
        exit(0);

    } 
	else if (pid > 0) {
    
    
        sleep(1);
        setpgid(pid,pid); //让子进程自立门户,成为进程组组长,以它的pid为进程组id
        sleep(6);
        printf("\n");
        printf("父进程 ID == %d\n", getpid());
        printf("父进程的父进程 ID == %d\n", getppid());
        printf("父进程组 ID == %d\n", getpgid(0));

        sleep(5);
        setpgid(getpid(),getppid()); // 改变父进程的组id为父进程的父进程
        printf("\n----父进程组ID被改变后的组 ID == %d\n",getpgid(0));
        //若是用ctrl-c杀不死,就用kill命令杀死 kill -9 进程ID
        while(1);
    }
    return 0;
}

3. 세션

   Linux 세션은 일반적으로 쉘 세션을 나타냅니다. 셸 세션은 터미널의 현재 상태이며 터미널에는 하나의 세션만 있을 수 있습니다. 새 터미널을 열면 항상 새 셸 세션이 생성됩니다. 이것은 세션이 우리가 쉘과 상호 작용하는 프로세스임을 보여줍니다. 프로세스 간 관계 측면에서 세션은 하나 이상의 프로세스 그룹으로 구성됩니다.

3.1 세션 생성

세션을 생성하려면 다음 6가지 사항에 주의해야 합니다.

1、调用进程不能是进程组组长,该进程变成新会话首进程(session header)
2、该进程成为一个新进程组的组长进程。
3、需有root权限(ubuntu不需要)
4、新会话丢弃原有的控制终端,该会话没有控制终端
5、该调用进程是组长进程,则出错返回
6、建立新会话时,先调用fork, 父进程终止,子进程调用setsid

3.2 getsid 함수

함수 함수:
  프로세스의 세션 ID 가져오기
헤더 파일:
  #include <unistd.h>
함수 프로토타입:
  pid_t getsid(pid_t pid)
함수 매개변수:
  pid: 프로세스 id, 0이면 세션 ID를 본다는 의미 현재 프로세스의.
반환 값:
  성공: 호출 프로세스의 세션 ID 반환,
  실패: -1, errno 설정

ps ajx시스템의 프로세스를 보는 명령입니다.
  파라미터 a는 현재 사용자의 프로세스뿐만 아니라 다른 모든 사용자의 프로세스를 나열하는 것을 의미하고,
  파라미터 x는 제어 단말의 프로세스뿐만 아니라 제어 단말이 없는 모든 프로세스를 나열한다는 의미이며,
  파라미터 j는 작업 제어 정보와 관련된 프로세스를 나열합니다.

그룹 리더 프로세스는 새 세션의 리더 프로세스가 될 수 없으며, 새 세션의 리더 프로세스는 리더 프로세스가 되어야 합니다.

3.3 setsid 함수

기능:
  세션을 생성하고 새 세션의 ID이기도 한 자체 ID로 프로세스 그룹 ID를 설정합니다.
헤더 파일:
  #include <unistd.h>
함수 프로토타입:
  pid_t setsid(void),
함수 매개변수:
  없음.
반환 값:
  성공: 호출 프로세스의 세션 ID 반환,
  실패: -1, setid errno
참고:
  setsid 함수를 호출하는 프로세스는 새 회장이자 새 그룹 리더입니다.

3.4 예시:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
    
    
    pid_t pid;
    if ((pid = fork())<0) {
    
    
        perror("fork");
        exit(1);

    } else if (pid == 0) {
    
    

        printf("子进程ID == %d\n", getpid());
        printf("子进程组ID == %d\n", getpgid(0));
        printf("子进程会话ID == %d\n", getsid(0));

        sleep(8);
        setsid();	//子进程非组长进程,故其成为新会话首进程,且成为组长进程。该进程组id即为会话进程

        printf("改变后:\n");

        printf("子进程ID == %d\n", getpid());
        printf("子进程组ID == %d\n", getpgid(0));
        printf("子进程会话ID == %d\n", getsid(0));

        sleep(10);

        exit(0);
    }
    while(1);
    return 0;
}

4. 데몬

  데몬(elf) 프로세스는 리눅스에서 백그라운드 서비스 프로세스로 보통 컨트롤 터미널과 독립적으로 특정 작업을 수행하거나 발생하는 특정 이벤트를 처리하기 위해 대기한다. 일반적으로 d로 끝나는 이름이 사용됩니다.
  Linux 백그라운드의 일부 시스템 서비스 프로세스에는 제어 터미널이 없으며 사용자와 직접 상호 작용할 수 없습니다. 사용자 로그인 및 로그아웃에 영향을 받지 않고 항상 실행되며 모두 데몬 프로세스입니다. 예: 사전 읽기 및 버퍼링 출력 메커니즘 실현, ftp 서버, nfs 서버 등
   데몬을 생성하기 위해 가장 중요한 단계는 setsid 함수를 호출하여 새 세션을 생성하고 세션 리더가 되는 것입니다.

4.1 데몬 모델 생성

1、创建子进程,父进程退出
所有工作在子进程中进行形式上脱离了控制终端
2、在子进程中创建新会话
  setsid()函数
  使子进程完全独立出来,脱离控制
3、改变当前目录为根目录
  chdir()函数
  防止占用可卸载的文件系统
  也可以换成其它路径
4、重设文件权限掩码
  umask()函数
  防止继承的文件创建屏蔽字拒绝某些权限
  增加守护进程灵活性
5、关闭文件描述符
  继承的打开文件不会用到,浪费系统资源,无法卸载
6、开始执行守护进程核心工作
7、守护进程退出处理程序模型																	

4.2 예시:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
void daemonize(void)
{
    
    
    pid_t pid;
    /*
     * * 成为一个新会话的首进程,失去控制终端
     * */
    if ((pid = fork()) < 0) {
    
    
        perror("fork");
        exit(1);
    } else if (pid != 0) /* parent */
        exit(0);
    setsid();
    /*
     * * 改变当前工作目录到/目录下.
     * */
    if (chdir("/") < 0) {
    
    
        perror("chdir");
        exit(1);
    }
    /* 设置umask为0 */
    umask(0);
    /*
     * * 重定向0,1,2文件描述符到 /dev/null,因为已经失去控制终端,再操作0,1,2没有意义.
     * */
    close(0);
    open("/dev/null", O_RDWR);
    dup2(0, 1);
    dup2(0, 2);
}

int main(void)
{
    
    
    daemonize();
    while(1); /* 在此循环中可以实现守护进程的核心工作 */
}

위의 내용은 이번 공유입니다. 모두에게 도움이 되길 바랍니다. 함께 더 많은 새로운 지식을 배우기 위해 블로거를 팔로우하는 것을 환영합니다!

Guess you like

Origin blog.csdn.net/qq_44177918/article/details/130333584