FIFO에 대한 질문입니다.

이기문의 이미지

프로젝트 때문에 리눅스 프로그래밍을 배우면서 짜고있는 학생입니다.

제가 FIFO를 이용해서 두 프로세스 간에 통신을 구현하고 싶거든요.

process 1에서는 쓸 필요가 있을때 FIFO에 내용을 쓰고
process 2에서 1초마다 한번씩 FIFO를 읽어서 FIFO에 내용이 있으면 읽어오고 없으면 그냥 읽기만 하고 넘어가는 식으로 프로그래밍 하고 싶습니다.

FIFO때문에 두 프로세스가 멈춰서는 않되기때문에 BLOCK을 걸지 않고
NONBLOCK 옵션을 쓰려고 하거든요.

그래서

process 1 에서는
open(.... , O_WRONLY) 로 FIFO를 열고 거기에 써주고..
process 2 에서는
open(.... , O_RDONLY | O_NONBLOCK) 로 FIFO를 열어서 거기서 읽어오게 하고 싶습니다.

생각에는 process 1 이 가끔가다가 write해주면 process 2가 1초에 한번씩 실행되면서 FIFO를 읽어들여서 만약에 write내용이 있으면 받아들이고 아니면 0byte를 읽을것 같은데..

write에사 broken pipe 되버리고 마네요..

조언 부탁드립니다.

만일 좀 더 자세한 소스가 필요하시면 말씀해주세요.

익명 사용자의 이미지

process 1 에서 혹시 process 2가 전부 읽어가기전에 close하지는 않는지요?

이기문의 이미지

아.. process 1에 process 2가 FIFO의 내용을 읽었는지 않읽었는지 체크하는 부분이 없네요.

그냥 쓰고 close 하는 방식으로 해놨습니다.

그부분이 문제가 있는것 같으네요.

어떻게 해결해야 될까요?
그냥 sleep등으로 읽어갈때까지 시간여유를 좀 주어야 되나요?

감사합니다. ^^

이기문의 이미지

소스코드 다시한번 올려봅니다..
아래는 process 1의 소스입니다.

    pipe_fd = open(FIFO_NAME, O_WRONLY);

    if (pipe_fd != -1) {
          while(bytes_sent < 50) {
                res = write(pipe_fd, buffer.c_str(), BUFFER_SIZE);
            if (res == -1) {
                fprintf(stderr, "Write error on pipe\n");
                exit(EXIT_FAILURE);
            }
            bytes_sent += res;
          }
          sleep(2);
          (void)close(pipe_fd);
    }
    else {
        exit(EXIT_FAILURE);
    }

    printf("Process %d finished\n", getpid());
    exit(EXIT_SUCCESS);

아래는 process 2의 소스입니다.

    if (access(FIFO_NAME, F_OK) == -1)  {
            res = mkfifo(FIFO_NAME, 0777);
            if (res != 0 )      {
                    fprintf(stderr, " Could not create fifo %s\n", FIFO_NAME);
                    exit(EXIT_FAILURE);
            }
    }


    memset(buffer, '\0', sizeof(buffer));

    pipe_fd = open(FIFO_NAME, O_RDONLY | O_NONBLOCK);

    if (pipe_fd != -1) {
        do {
            res = read(pipe_fd, buffer, BUFFER_SIZE);
            bytes_read += res;
        } while (res > 0);
        printf("fifo content : %s:\n", buffer);
        (void)close(pipe_fd);
    }
    else {
        exit(EXIT_FAILURE);
    }

process 2는 while를 사용해서 1초당 한번씩 실행되게 되어있습니다.
그리고 혹시나 해서 process 1에서 sleep(2) 를 넣어봤습니다.
하지만 결과는 같은것 같습니다.

그럼 조언 부탁드립니다.

이기문의 이미지

에구.. 제가 바보같은 짓을.. ^^;;

read 할 때 while 루프 내에서 매번 FIFO를 열고닫고 해놓아서 않된 것 같으네여.. ^^;;

moonzoo의 이미지

process1에서 write하고자 할때

process2에서 해당 FIFO를 close했다면

write 를 하지 못합니다.

즉 read할려는 process가 해당 FIFO를 open하고 있을때에만

writel할려는 process가 write 할 수 있습니다.

이기문의 이미지

소스코드 다시한번 올려봅니다..
제 생각대로 수정해봤는데..
한군데서는 되고 한군데서는 않되기에 문제가 있나 싶어서 다시 질문드립니다.

아래는 process 1의 소스입니다.

    
처음에 constructor에서 한번만 실행합니다.
    if (access(FIFO_NAME, F_OK) == -1)  { 
            res = mkfifo(FIFO_NAME, 0777); 
            if (res != 0 )      { 
                    fprintf(stderr, " Could not create fifo %s\n", FIFO_NAME); 
                    exit(EXIT_FAILURE); 
            } 
    } 

    pipe_fd = open(FIFO_NAME, O_WRONLY); 


다음 부분은 write할 필요가 있을때마다 한번씩 실행합니다.


    if (pipe_fd != -1) { 
          while(bytes_sent < 50) { 
                res = write(pipe_fd, buffer.c_str(), BUFFER_SIZE); 
            if (res == -1) { 
                fprintf(stderr, "Write error on pipe\n"); 
                exit(EXIT_FAILURE); 
            } 
            bytes_sent += res; 
          } 
    }

다음부분은 destructor에서 한번만 실행합니다.
          (void)close(pipe_fd);  

아래는 process 2의 소스입니다.

    if (access(FIFO_NAME, F_OK) == -1)  { 
            res = mkfifo(FIFO_NAME, 0777); 
            if (res != 0 )      { 
                    fprintf(stderr, " Could not create fifo %s\n", FIFO_NAME); 
                    exit(EXIT_FAILURE); 
            } 
    } 


    memset(buffer, '\0', sizeof(buffer)); 

    pipe_fd = open(FIFO_NAME, O_RDONLY | O_NONBLOCK); 

    while(1)
    {

    if (pipe_fd != -1) { 
        do { 
            res = read(pipe_fd, buffer, BUFFER_SIZE); 
            bytes_read += res; 
        } while (res > 0); 
        printf("fifo content : %s:\n", buffer); 
    }
    sleep(1)
    }

    (void)close(pipe_fd); 

process 2는 while를 사용해서 1초당 한번씩 실행되게 되어있습니다.

process 2에서는 FIFO를 한번만 열고 닫으면서 while루프로 1초에 한번씩 process가 write 한 내용을 읽어옵니다.
그리고 원하는 작업이 끝나면 마지막에 process 2가 죽으면서 FIFO를 닫습니다.

이렇게 했는데 write 할수 없다고 에러가 자꾸 뜨네요..

그럼 조언 부탁드립니다.

stoneshim의 이미지

오류번호를 말씀해주세요.

우리 모두 리얼리스트가 되자. 그러나 가슴에 이룰 수 없는 꿈을 가지자

댓글 달기

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