fork() 와 소켓의 연관성에 대한 질문...

lastsky의 이미지

안녕하세요. Beej Guid to NP 를 공부하는 중에 궁금한점이 생겨서요.
이제 막 리눅스 프로그래밍을 시작해서 잘 모릅니다. ㅠㅠ
아래는 궁금증이 발생한 소스 입니다.

    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <string.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <sys/socket.h>
    #include <sys/wait.h>

    #define MYPORT 3490    /* the port users will be connecting to */

    #define BACKLOG 10     /* how many pending connections queue will hold */

    main()
    {
        int sockfd, new_fd;  /* listen on sock_fd, new connection on new_fd */
        struct sockaddr_in my_addr;    /* my address information */
        struct sockaddr_in their_addr; /* connector's address information */
        int sin_size;

        if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
            perror("socket");
            exit(1);
        }

        my_addr.sin_family = AF_INET;         /* host byte order */
        my_addr.sin_port = htons(MYPORT);     /* short, network byte order */
        my_addr.sin_addr.s_addr = INADDR_ANY; /* auto-fill with my IP */
        bzero(&(my_addr.sin_zero), 8);        /* zero the rest of the struct */

        if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) \
                                                                      == -1) {
            perror("bind");
            exit(1);
        }

        if (listen(sockfd, BACKLOG) == -1) {
            perror("listen");
            exit(1);
        }

        while(1) {  /* main accept() loop */
            sin_size = sizeof(struct sockaddr_in);
            if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, \
                                                          &sin_size)) == -1) {
                perror("accept");
                continue;
            }
            printf("server: got connection from %s\n", \
                                               inet_ntoa(their_addr.sin_addr));
            if (!fork()) { /* this is the child process */
                if (send(new_fd, "Hello, world!\n", 14, 0) == -1)
                    perror("send");
                close(new_fd);
                exit(0);
            }
            close(new_fd);  /* parent doesn't need this */

            while(waitpid(-1,NULL,WNOHANG) > 0); /* clean up child processes */
        }
    }

간단한 소켓 스트림 서버인데요. 포크의 여부를 판단해 메시지를 전송하는 부분에서 궁금증이 생기네요..

Quote:

if (!fork()) { /* this is the child process */
if (send(new_fd, "Hello, world!\n", 14, 0) == -1)
perror("send");
close(new_fd);
exit(0);
}

if에서 !fork()로 체크해주는데요, 접속이 이루어지면 소켓 자체에서 child 프로세스를 직접 fork() 하게 되는건가요? 분명 child process를 만드는 부분이 없어서...

그리고,

Quote:

while(waitpid(-1,NULL,WNOHANG) > 0); /* clean up child processes */

이부분에서는 뭘 의미하는건가요? 프로세스에대한 개념이 확실치 않아 힘드네용 ㅠㅠ 혹시 프로세스의 생성과 관리에 관련되어 참조해볼만한 문서가 있을까요? 이부분에 관련되어 가진 책은 오릴리에서 나온 Unix System Programming 과 박장수씨의 리눅스 커널분석 2.4 라는 책이 전부네요.

혹시 인터넷에서 볼만한 문서라도 있으면 알려주시면 정말 감사드리겠습니다.

항상 행복하시길~.

서지훈의 이미지

fork()는 어떤 순간에 하는게 아니고...
fork() 부분에서 무조건 자식을 생성합니다.
자식을 생성하고나서 아래의 작업을 하게됩니다.
fork()의 반환값으로 0보다 크면 parent, 0이면 child, -1 이면 에러입니다.
그래서 !fork() 이건 child를 가르킵니다.

그리고 waitpid()는 특정 pid가 끝나기를 기다리게 됩니다.
그러나 wpid값이 -1이 되면은 어떤 프로세스라도 종료를 하게 되면(여기선 자식 프로세스가 죽기를 기다렸다가 자원을 환원한다), 다음 작업을 하게됩니다.
만약 이러한게 없으면 일명 zombie process가 생겨 먹은 자원을 중앙에 환원하지 않고 죽은 프러소세그ㅏ 그대로 유지가 되게 됩니다.
wiatpid()는 이러한 것을 막아 주는 역활을 하게됩니다.

그리고 좀 더 자세한 내용은 Stevens의 APUE를 참조 하시길...

<어떠한 역경에도 굴하지 않는 '하양 지훈'>

#include <com.h> <C2H5OH.h> <woman.h>
do { if (com) hacking(); if (money) drinking(); if (women) loving(); } while (1);

indie의 이미지

우선은 man 페이지를 참고 하세요.
fork()같은 경우는 리턴값을 받아서 저장하면 나중에
부모 프로세스에서 써먹을 대가 있습니다.

pid = fork();
if( pid == 0 ) 
    ; // child
else if ( pid > 0 ) 
    ; // parent
else 
    ; //error

그리고 waitpid역시 man에서 보면
첫번재가 -1 이면 자신이 만든 아무 자식이나 종료하길 기다리고
세번째 인자가 WNOHANG인 경우는 종료한 놈이 없으면 즉각
리턴하라는거 같군요...

집에나 갈까?

lastsky의 이미지

답변주셔서 너무나 고마워요.
APUE 를 구입해야겠네여.. ^^

맨페이지가 나오지 않아 ftp.kernel.org 에서 받아서 덮어버렸더니 나오네요 ㅎㅎ... 뭐 make install 이런거 하라던데 데네요? -_-;;

어쨌든 너무 고마워요~ 좀더 내공을 쌓아야 겠습니다.

mudori의 이미지

한개의 좀비 프로세스가 계속 남는건 무슨 이유인가요?
아무리 바꿔줘도 하나가 꼭 남습니다.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.