FIFO :double read?

BarracuTa의 이미지

http://users.unitel.co.kr/~sangeun5/linux/lpg_6_3_3.html
위 주소에 내용을 따라해보던중
서버 부분을 약간 바꿔서 해보자는 취지에 아래 코드와 같이 바꾸어보았습니다..

실행을 예측해보았을때
printf("%dReceived string : %s \n ",i,readbuf);이문장이 한번만 실행 될줄알았는데 2번 루프를 돌더군요 이유가 먼가요?
클라이언트쪽에선 FIFO에 딱 한번 쓰기를 한거같은데 이유를 잘모르겠습니다.. 서버쪽에선 한번에 read후 블록되어져 대기해야하는거 아닌가요?
결과입니다...

[barracuTa@NES ch7]$ ./fifos&
[1] 6868
[barracuTa@NES ch7]$ ./fifoc 안녕하세요
안녕하세요
0Received string : 안녕하세요
 1Received string : 안녕하세요
[barracuTa@NES ch7]$ ./fifoc 반갑습니다.
반갑습니다.
 2Received string : 반갑습니다.
 3Received string : 반갑습니다.
[barracuTa@NES ch7]$ ./fifoc 감사합니다.
감사합니다.
 4Received string : 감사합니다.
 5Received string : 감사합니다.
[barracuTa@NES ch7]$

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/stat.h>

#define FIFO_FILE "myfifo"

int main()
{
  FILE *fp;
  int fd;
  char readbuf[80];

  umask(0);

  mknod(FIFO_FILE,S_IFIFO|0666,0);
  int i=0;
  while(1)
    {

      if((fd=open(FIFO_FILE,O_RDONLY/*|O_NONBLOCK*/))==-1)
        {
          perror("open");
          exit(1);
        }

      read(fd,readbuf,80);

      printf("%dReceived string : %s \n ",i,readbuf);
      i++;
      close(fd);
    }

  return (0);
}

클라이언트부분은 변형된건 없습니다..
클라이언트

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

#define FIFO_FILE "myfifo"

int main(int argc,char *argv[])
{
  FILE *fp;

  if(argc!=2)
    {
      printf("USE : fifoc [stirng]\n");
      exit(1);
    }

  if((fp=fopen(FIFO_FILE,"w"))==NULL)
    {
      perror("fopen");
      exit(1);
    }
  printf("%s\n",argv[1]);
  fputs(argv[1],fp);
  fclose(fp);
  return 0;
}
doldori의 이미지

이렇게 해야 할 듯하네요.

size_t nread = read(fd,readbuf,80);
if (nread)
{
    readbuf[min(nread, 79)] = '\0';
    printf("%dReceived string : %s \n ",i,readbuf); 
    i++; 
}
익명 사용자의 이미지

stream에 대한 이해가 필요한듯합니다.
클라이언트(쓰는 프로그램)가 한번에 보낸 사이즈만큼, 서버(읽는 프로그램)가 한번에 수신한다는 착각을 하시면 안됩니다.
단지 현재 fifo에 수신된 것을 읽는다는(읽는 시점에 따라 그때 그때 다르겠지요.)....
적어도 fifo에 1바이트 이상이면 읽어들이게 됩니다(read에서 리턴하게 된다는..) 이는 커널(fifo도 커널을 경유)이 메시지의 경계를 알지 못하기 때문입니다.
또한, 스트림에서는 커널에게 메시지의 경계를 지정할 방법이 마땅치 않습니다.
그래서, 사용자 수준(프로그래머가)에서 메시지의 경계를 구분하도록 코딩해야 합니다.

그러므로, 이러한 stream유형의 처리에서는 반드시, read()의 리턴값을 검사하여 얼마나 읽었는지를 파악해야 할것입니다.

댓글 달기

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