read();함수의 블럭킹에 대해서...

불량청년의 이미지

안녕하세요?

다름이 아니오라 아래와 같은 코드를 실행시 파이프의 출력을

받지 못하는 부모 프로세스는 read();에서 블럭킹이 되어야

하는데, 시그널 처리(자식프로세스 종료)를 해주면 블럭킹이

안되는 현상이 발생하네요.

제가 알고 있기로는 read();는 아래 코드에서 블럭되어야 하는걸로

알고 있습니다. 제가 잘 못 알고 있는 건가요?

시그널 처리를 안해주면 read();에서 블럭되거든요.

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>

#define BUFSIZE 30

void sig_handler(int sig);

int main(int argc, char **argv)
{
        int fd[2];
        char buffer[BUFSIZE];
        pid_t pid;
        int stat;
        struct sigaction s_st;

        memset(buffer, 0x00, BUFSIZE);

        s_st.sa_handler = sig_handler;
        sigemptyset(&s_st.sa_mask);
        s_st.sa_flags = 0;

       stat = sigaction(SIGCHLD, &s_st, 0);
        if(stat != 0)
                puts("sigaction() error");

        stat = pipe(fd);
        if(stat == -1)
        {
                puts("pipe() error");
                exit(1);
        }

        pid = fork();
        if(pid == -1)
        {
                puts("fork() error");
                exit(1);
        }
        else if(pid == 0)
        {
                write(fd[1], "Good!", 6);
          //      sleep(2);   /* 일부러 부모프로세스에서 블럭되도록 주석처리
                read(fd[0], buffer, BUFSIZE);
                printf("Child Process Out : %s\n", buffer);
        }
        else
        {
                read(fd[0], buffer, BUFSIZE);
                printf("Parent Process Out : %s\n", buffer);
                write(fd[1], "Really Good", 12);
                sleep(10);
        }
        return 0;
}

void sig_handler(int sig)
{
        pid_t pid;
        int retun;

        if((pid = waitpid(-1, &retun, WNOHANG)) > 0)
                printf("ID : %d, return : %d\n", pid, WEXITSTATUS(retun));
}
pynoos의 이미지

read 의 return 값이 0인지 -1 인지 확인하여 주시고

-1이라면, errno==EINTR 인지 확인하여 다시 read 할 수 있도록 만들어주셔야합니다. 귀찮지만, 모든 return 값을 확인하여 error 처리하는 것은 기본이지요.

mach의 이미지

*참고
모든 유닉스 시스템호출(system call)중 blocking모드로 동작하는 것은
다음의 경우에 리턴됩니다.
1) 작업성공(호출성공)
2) 작업실패(에러발생)
3) 시그널수신(임의의 시그널이 해당 프로세스에 도착시)
이중 3번째 경우입니다.
sigchild 시그널이 수신되어 블럭에서 탈출하는 것은 지극히 당연합니다.

* 지극히 당연한 얘기지만, 만일 블럭킹모드로 동작할때, 시그널수신시
탈출하지 않는다면, CTRL+C의 기능(signal로 구현됨)이 동작안되겠지요?
그러하니, 위에 pynoos님의 말씀대로 에러처리를 수행하는것이 기본입니다.
꼭 read만이 아니라, 다른 블럭킹모드 시스템호출 전체에 대해서 고려해
주셔야 합니다.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

bw001730의 이미지

시스템콜 호출중에 시그널이 도착한다면..
그리고 프로세스가 그 시그널을 무시하지 않는다면
시스템콜은 (블럭킹되는) 인터럽트됩니다.
자식이 종료하고 SIGCHLD가 부모로 도착했고
부모가 시그널 처리를 했기 때문에
read()에서 대기중이다가 인터럽트 당한것 같습니다.
역시 저도 에러처리를 해보면 알것이다 생각듭니다.

SIGCHLD는 프로세스의 기본동작은 (SIG_DFL)은 무시하는 것이라서
처음에는 인터럽트 안된것 같네요

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.