프로그램 지침 닫기

프로그램 지침 닫기

"How Linux Works"라는 책에는 일반적인 종료 프로세스(init 시스템과 무관)가 다음과 같이 나와 있습니다.

  1. init를 수행하려면 각 프로세스를 완전히 종료해야 합니다.
  2. 일정 시간이 지난 후에도 프로세스가 응답하지 않으면 init는 프로세스를 종료하고 TERM 신호를 먼저 시도합니다.
  3. TERM 신호가 비활성화된 경우 init는 모든 지연에 대해 KILL 신호를 사용합니다.
  4. 시스템은 시스템 파일을 제자리에 잠그고 종료를 준비합니다.
  5. 시스템은 루트를 제외한 모든 파일 시스템을 마운트 해제합니다.
  6. 시스템이 다시 마운트되었습니다.루트 파일 시스템 읽기 전용.
  7. 체계버퍼링된 모든 데이터를 파일 시스템에 쓰기동기화 절차를 통해
  8. 마지막 단계는 boot(2) 시스템 호출을 통해 커널에 재시작 또는 중지를 지시하는 것입니다. 이는 초기화나 다시 시작, 일시 중지 또는 전원 끄기와 같은 도우미 프로그램을 통해 수행할 수 있습니다.

파일 시스템이 읽기 전용인 경우 동기화는 어떻게 해당 버퍼에 쓰기를 합니까?

답변1

당신이 놀란 것은 맞습니다. 이 명령은 의미가 없습니다. 책에 이런 내용이 나와 있다면 그것은 성급하고 오해를 불러일으키는 것입니다.

파일 시스템을 마운트 해제하거나 읽기 전용으로 마운트하면 모든 데이터가 디스크에 기록됩니다. umount명령 또는 반환이 수행 되면 mount -o remount,ro모든 데이터가 디스크에 기록되었으며 sync더 이상 수행할 작업이 없습니다. 이전에 호출하는 것은 의미가 없으며 sync(어차피 마운트 해제 작업에 의해 데이터가 기록됨) 이후에 호출하는 것도 의미가 없습니다(아무 작업도 수행하지 않음).

나는 이것이 일부 고대 유닉스 시스템에서는 사실이 아니라고 생각합니다.sync 앞으로제거. 나중에 전화하는 것은 여전히 ​​​​이치에 맞지 않습니다.

파일 시스템 이상의 기능을 사용하면 특정 상황에서 sync특정 작업을 수행할 수 있습니다. 예를 들어, Linux에서는 syncRAID 어레이의 메타데이터가 디스크에 기록되도록 하는 것이 가능하다고 생각합니다 . 이는 파일 시스템을 읽거나 쓰지 않고도 유용합니다.

답변2

fs 읽기 전용을 다시 마운트하면 프로세스에서 rw 모드의 모든 파일 수준 쓰기 요청 및 open() 호출이 차단되므로 데이터 및 fs 구조를 더 이상 수정할 수 없습니다. 버퍼링은 블록 장치 드라이버와 파일 시스템 드라이버 사이에 위치하므로 시스템에 더티 버퍼가 있는 경우 기본 미디어에 기록해야 합니다.

일반적인 스택은 다음과 같습니다.

  • 프로세스
  • 커널 파일 io API
  • fs드라이버 예:ext3fs
  • blkdev코어, 추상화 계층, API, 많은 유용한 기본 요소, 기본 동작 등의 일부입니다. 또한 이 계층은 버퍼와 디스크 캐시를 관리하고 커널과의 교환을 제공합니다.
  • scsiLinux 하위 시스템 과 같은 장치 드라이버를 차단합니다 .
  • 저장 장치

루프는 다양한 수준에 존재할 수도 있습니다. 예를 들어 파일을 루프 장치로 사용하여 저장소, LUKS장치 암호화 등을 지원할 수 있습니다 .

답변3

다음은 종료를 수행하는 코드의 일부입니다(System V 스타일 구현).

/*
 *  Kill all processes, call /etc/init.d/halt (if present)
 */
void fastdown()
{
    int do_halt = (down_level[0] == '0');
    int i;
#if 0
    char cmd[128];
    char *script;

    /*
     *  Currently, the halt script is either init.d/halt OR rc.d/rc.0,
     *  likewise for the reboot script. Test for the presence
     *  of either.
     */
    if (do_halt) {
        if (access(HALTSCRIPT1, X_OK) == 0)
            script = HALTSCRIPT1;
        else
            script = HALTSCRIPT2;
    } else {
        if (access(REBOOTSCRIPT1, X_OK) == 0)
            script = REBOOTSCRIPT1;
        else
            script = REBOOTSCRIPT2;
    }
#endif

    /* First close all files. */
    for(i = 0; i < 3; i++)
        if (!isatty(i)) {
            close(i);
            open("/dev/null", O_RDWR);
        }
    for(i = 3; i < 20; i++) close(i);
    close(255);

    /* First idle init. */
    if (kill(1, SIGTSTP) < 0) {
        fprintf(stderr, "shutdown: can't idle init: %s.\r\n", strerror(errno));
        exit(1);
    }

    /* Kill all processes. */ 
    fprintf(stderr, "shutdown: sending all processes the TERM signal...\r\n");
    kill(-1, SIGTERM);
    sleep(sltime ? atoi(sltime) : 3);
    fprintf(stderr, "shutdown: sending all processes the KILL signal.\r\n");
    (void) kill(-1, SIGKILL);

#if 0
    /* See if we can run /etc/init.d/halt */
    if (access(script, X_OK) == 0) {
        spawn(1, cmd, "fast", NULL);
        fprintf(stderr, "shutdown: %s returned - falling back "
                "on default routines\r\n", script);
    }
#endif

    /* script failed or not present: do it ourself. */
    sleep(1); /* Give init the chance to collect zombies. */

    /* Record the fact that we're going down */
    write_wtmp("shutdown", "~~", 0, RUN_LVL, "~~");

    /* This is for those who have quota installed. */
#if defined(ACCTON_OFF)
# if (ACCTON_OFF > 1) && (_BSD_SOURCE || (_XOPEN_SOURCE && _XOPEN_SOURCE < 500))
    /* This is an alternative way to disable accounting, saving a fork() */
    if (acct(NULL))
        fprintf(stderr, "shutdown: can not stop process accounting: %s.\r\n", strerror(errno));
# elif (ACCTON_OFF > 0)
    spawn(1, "accton", "off", NULL);
# else
    spawn(1, "accton", NULL);
# endif
#endif
    spawn(1, "quotaoff", "-a", NULL);

    sync();
    fprintf(stderr, "shutdown: turning off swap\r\n");
    spawn(0, "swapoff", "-a", NULL);
    fprintf(stderr, "shutdown: unmounting all file systems\r\n");
    spawn(0, "umount", "-a", NULL);

    /* We're done, halt or reboot now. */
    if (do_halt) {
        fprintf(stderr, "The system is halted. Press CTRL-ALT-DEL "
                "or turn off power\r\n");
        init_reboot(BMAGIC_HALT);
        exit(0);
    }

    fprintf(stderr, "Please stand by while rebooting the system.\r\n");
    init_reboot(BMAGIC_REBOOT);
    exit(0);
}

먼저 볼 수 있듯이 프로세스 종료 부분은 다음과 같습니다.

sync();
fprintf(stderr, "shutdown: turning off swap\r\n");
spawn(0, "swapoff", "-a", NULL);
fprintf(stderr, "shutdown: unmounting all file systems\r\n");
spawn(0, "umount", "-a", NULL);

디스크에 데이터를 쓰는 데 사용됩니다 sync. 그런 다음 스왑을 닫고 모든 파일 시스템을 마운트 해제합니다. 그런 다음 실제 중지 또는 재시작이 발생합니다.

sync매뉴얼 페이지의 설명:

sync()는 파일 시스템 메타데이터 및 캐시된 파일 데이터에 대해 보류 중인 모든 수정 사항이 기본 파일 시스템에 기록되도록 합니다.

이 책은 약간 오래되었거나 다른 클로저 구현을 설명할 수 있습니다. 코드와 매뉴얼 페이지를 읽는 것도 Linux 작동 방식을 배우는 좋은 방법입니다.

관련 정보