gets,pipe에 관련된 기초 질문입니다.

firster의 이미지

여기 저기를 검색해봐도 정확한 답을 찾을 수가 없어서 질문을 올립니다.
아래의 코드를 컴파일하고 실행시키면 하나의 문자만 받고 종료하는군요.

#include <stdio.h>
#include <unistd.h>

void main(){
   int fd[2],status;
   pid_t pid1,pid2;
   char str1[100];
   char str2[100];

   status = pipe(fd);
   pid1 = fork();
   if(pid1 == 0){//child
      printf("This is child[%d]!\n",pid1);
      printf("Input string send to parent:");
      printf("[%s]",gets(str1)); --- Mark 1
      sprintf("[%s]",str1);
      write(fd[0],str1,8);
   }
   else{
      printf("This is parent[%d]!!\n",pid1);
      read(fd[1],str2,sizeof(str2));
   }
}

실행결과입니다.

This is parent[16064]!!
This is child[0]!
Input string send to parent:[firster:/test/pipe]43 #[a]d
d: Command not found.

질문 1: gets는 분명 엔터를 입력할 때까지 문자열을 입력받는 것으로 알고있는데, 왜 한글자 입력하자마자 출력(코드의 Mark 1 부분)이 되는거죠?
질문 2: 프로그램 실행 중에 쉘 프롬프트가 뜨는 이유는 무엇 때문인지요?
질문 3: 실행시킬 때마다 parent 코드부분이 먼저 출력되는 것 같습니다.
항상 그런가요?
질문 4: 이 프로그램의 최종목적인데 child process에서 문자열을 입력받고 파이프로 쓰면 parent process에서 문자열을 출력하려고 합니다. 부족한 부분 좀 가르쳐 주십시오. 힌트라도 주시면 감사하겠습니다.

가야할 길이 너무 멀어서 한숨만 나오는군요 :oops: :(

pynoos의 이미지

pipe 의 fd[0] 이 reading 용입니다.

firster의 이미지

예..man으로 검색해봤지만 자세히 보지는 않았는데, fd[0]은 reading이라고 나오는군요 :oops: .

저는 Uresh Vahalia의 Unix Internals에 있는 내용만 읽다보니까...
아래는 관련된 문장을 책에서 발췌한 것입니다.

6.2.3 SVR4 Pipes
...
status = pipe(int fildes[2]);
In SVR4, this call creates two independent, first-in first-out, I/O channels that are represented by the two descriptors. Data written to fildes[1] can be read from fildes[0], and data written to fildes[0] can be read from fildes[1]. ...
...

SVR4만 그런가보군요.

moonzoo의 이미지

Quote:

질문 1: gets는 분명 엔터를 입력할 때까지 문자열을 입력받는 것으로 알고있는데, 왜 한글자 입력하자마자 출력(코드의 Mark 1 부분)이 되는거죠?
질문 2: 프로그램 실행 중에 쉘 프롬프트가 뜨는 이유는 무엇 때문인지요?

자식 프로세스와 부모 프로세스가 "동시에" 진행되기 때문에 그렇습니다.
부모쪽에서 기다리는 입장이니 부모쪽에 sleep(5) 정도를 두어서
시간차를 두는게 좋을듯 합니다.

Quote:

질문 3: 실행시킬 때마다 parent 코드부분이 먼저 출력되는 것 같습니다.
항상 그런가요?

아닙니다.. parent와 child 둘중 어느 코드가 먼저 선행될지는 예측할 수 없습니다..순차적인것을 원한다면 sleep등을 간단히 이용할수 있겠네요.

Quote:

질문 4: 이 프로그램의 최종목적인데 child process에서 문자열을 입력받고 파이프로 쓰면 parent process에서 문자열을 출력하려고 합니다. 부족한 부분 좀 가르쳐 주십시오. 힌트라도 주시면 감사하겠습니다

다른 분이 이미 얘기 하셨는데.. fd[0]에 읽기용이고, fd[1]이 쓰기용입니다.

ps. 글구 코드 중간에 sprintf("[%s]",str1); 이 문장은 어떤 용도로 쓰셨나요?
에러는 안나는데..어떤 결과를 낳는지 모르겠군요.(실수인가여? )

firster의 이미지

답변에 감사드립니다 :o .

Quote:

ps. 글구 코드 중간에 sprintf("[%s]",str1); 이 문장은 어떤 용도로 쓰셨나요?
에러는 안나는데..어떤 결과를 낳는지 모르겠군요.(실수인가여? )

예, 실수로 지우지 못했네요 :oops:.
첨에 sprintf를 사용했다가 바로 윗줄의 printf로 바꿨는데, 아규가 뒤섞여있군요.
그런데, gets 함수 실행시엔 입력이 끝날 때까지 부모 프로세스는 blocking되지 않나요? 음..1 번 질문에 대한 답은 제대로 이해가 되지 않는군요.

글 추가합니다.
아래와 같이 코드를 수정하였습니다.

void main(){
   int fd[2],status;
   pid_t pid1,pid2;
   char str1[100];
   char str2[100];

   status = pipe(fd);
   pid1 = fork();
   if(pid1 == 0){//child
      printf("This is child[%d]!!\n",pid1);
      printf("Input test string:");
      gets(str1);
      printf("[%s]",str1);
      write(fd[1],str1,sizeof(str1));
   }
   else{
      printf("This is parent[%d]!\n",pid1);
      read(fd[0],str2,sizeof(str2));
      printf("[%s]",str2);
   }
}

몇번 테스트해본 결과는 아래와 같이 2가지 경우로 나오는군요.

[firster:/test/pipe]45 #pipe_test
This is parent[13462]!
This is child[0]!!
Input test string:232
[232][232][firster:/test/pipe]46 #pipe_test
This is child[0]!!
This is parent[31329]!
Input test string:123
[123][123][firster:/test/pipe]47 #

그런데, 여전히 위의 1번 질문에 대한 답은 파악이 안됩니다.
답변에 감사드립니다.

moonzoo의 이미지

Quote:

그런데, gets 함수 실행시엔 입력이 끝날 때까지 부모 프로세스는 blocking되지 않나요? 음..1 번 질문에 대한 답은 제대로 이해가 되지 않는군요.

fork()에 대해서 약간 잘못 생각하시고 계신듯 합니다.

fork() 후에는 child와 parent라는 2개의 프로세스가 동작하는 것입니다.
(동일한 코드를 가지는)

예를 들어 우리가 a라는 프로세스에서 gets()로 stdin에서 입력을

기다리고 있다고 해서 b라는 프로세스에서 blocking이 될 이유가 전혀

없는 것입니다. a와 b는 독립적으로 실행이 되고 있기 때문이죠.

else 부분이 parent가 타는 루틴인데..sleep(5)정도를 넣어보시고

결과를 확인해보세요..

또한 위에서 사용하신 if() ~ else문 밖에 printf("\n테스트\n"); 라고

해보세요.. 나중에 실행해 보면 테스트가 2번 찍힐 것입니다.

child에서 한번 실행하고 parent에서도 한번 실행하기 때문이죠..

뉴피엘의 이미지

이런경우엔.

부모프로세스에서 read를 하기때문에.

read에서 블락킹됩니다.

자식프로세스의 gets와는 별개의 문제이고..

write할때까지 기달리게 됩니다.

我不知道

댓글 달기

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