pipe 사용에 대해..

dragem의 이미지

pipe(fd);

pid = fork();
	if(pid == 0)
	{
		dup2(fd[1], STDOUT_FILENO);
		if(execlp(buff[0], buff[0], NULL) < 0)
			printf("1err\n");
		exit(1);
	}
	else if(pid > 0)
	{
		waitpid(pid, NULL, 0);
	}




	pid = fork();
	if(pid == 0)
	{
		if(dup2(fd[0], STDIN_FILENO) != STDIN_FILENO)
			printf("error\n");
		if(dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO)
			printf("error\n");

		if(execlp(buff[1], buff[1], NULL) < 0)
			printf("2err\n");
		exit(1);
	}
	else if(pid > 0)
	{
		waitpid(pid, NULL, 0);
	}

$ 명령1 | 명령2

을 구현하고 싶어서 저렇게 구현해봤는데 잘 안되네요..
어디서 문제가 나는걸까요.. 참고로 buff[0]과 buff[1]은 명령1과 명령2를 나타냅니다..
gdb를 통해 디버깅을 하려고 했는데.. fork한 프로세스는 따라가지 않더군요..

nthroot의 이미지

waitpid(pid, NULL, 0); 일단 여기서 블럭이 될것 같네요.
signal(SIGCLD, SIG_IGN); 해주서야 할것 같구요.

그리고

if(dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO)
printf("error\n");

이 부분은 이상한것 같네요.
이 부분을 제외한 윗부분만으로 일단 PIPE는 될것 같은데요.

이부분의 메세지를 받는 부분을 만드셔야 할것 같구요.
한쪽에서 입력을 계속 받는 다면 루프에 빠질수도 있겠네요.

------식은이 처------
길이 끝나는 저기엔 아무 것도 없어요. 희망이고 나발이고 아무 것도 없어.

dragem의 이미지

pipe(fd);

pid = fork();
   if(pid == 0)
   {
      dup2(fd[1], STDOUT_FILENO);  //출력을 씀..
      if(execlp(buff[0], buff[0], NULL) < 0)
         printf("1err\n");
      exit(1);
   }
   else if(pid > 0)
   {
      waitpid(pid, NULL, 0);
   }




   pid = fork();
   if(pid == 0)
   {
      if(dup2(fd[0], STDIN_FILENO) != STDIN_FILENO) // 입력으로 읽음
         printf("error\n");

      if(execlp(buff[1], buff[1], NULL) < 0)
         printf("2err\n");
      exit(1);
   }
   else if(pid > 0)
   {
      waitpid(pid, NULL, 0);
   }

Quote:

waitpid(pid, NULL, 0); 일단 여기서 블럭이 될것 같네요.
signal(SIGCLD, SIG_IGN); 해주서야 할것 같구요.

블럭된다니 무슨 말이죠?
첫번째 waitpid()로 명령1을 기달린후 다 끝났으면 명령2를 실행시키려고 한것인데..

Quote:

if(dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO)
printf("error\n");

이 부분은 이상한것 같네요.
이 부분을 제외한 윗부분만으로 일단 PIPE는 될것 같은데요.


이상하게 될것 같은데 안되네요.. 그 부분을 빼고 실행해보면 첫번째 child process가 fork되서 fd[1]에 output을 넣는거 같은데요..

두번째 child에서는 fd[0]을 못 읽네요..

jemiro의 이미지

이렇게 하면 간단히 될꺼 같은데요?

dragem wrote:
       pid_t pid1, pid2, wait_pid;
 
       pipe(fd);

       pid1 = fork();
	if (pid1 == 0) 	{
		dup2(fd[1], STDOUT_FILENO);
		if(execlp(buff[0], buff[0], NULL) < 0)
			printf("1err\n");
		exit(1);
	}

	pid2 = fork();
	if(pid2 == 0) 	{
		if(dup2(fd[0], STDIN_FILENO) != STDIN_FILENO)
			printf("error\n");
		if(dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO)
			printf("error\n");

		if(execlp(buff[1], buff[1], NULL) < 0)
			printf("2err\n");
		exit(1);
	}
    
       do {
             wait_pid = waitpid(pid1,  NULL, 0);
        } while (wait_pid == -1 && errno == EINTR);

       do {
             wait_pid = waitpid(pid2,  NULL, 0);
        } while (wait_pid == -1 && errno == EINTR);


dragem의 이미지

같은결과가네요^^;

우후~ㅁ

feelpassion의 이미지

도움이 되었으면 좋겠네요^^

//executing command with pipeline
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main(int argc, char **argv)
{
	pid_t pid;
	int fd[2];

	if( (pipe(fd) == -1) ){
		perror("pipe()");
		exit(1);
	}

	pid = fork();
		
	switch(pid)
	{
	case -1:
		perror("fork()");
		exit(2);

	case 0:
		dup2(fd[1],1); //stdout이 임의적으로 fd[1]로 바뀐다.
		close(fd[1]);
		close(fd[0]);
		execlp("ls","ls",(char*)0);
	
	default:
		dup2(fd[0],0); //stdin이 생성된 fd[0]의 값으로 바뀐다.
		close(fd[0]);
		close(fd[1]);
		execlp("wc","wc",(char*)0);
		wait();
	} //End of case
}

남으로 창을 내겠소.
밭이 한참갈이 괭이로 파고 호미론 김을 메지요.
구름이 꼬인다 갈리있소. 새들의 노래는 공으로 들으랴오.
강냉이가 익거든 와자셔도 좋소.
왜 사냐건 웃지요.

dragem의 이미지

음..원래 pipe가 parent와 child 사이에만 대화가 통하게 되나요?

그림이 잘 안그려지네요... 으흠..

그런데 feelpassion님 말씀대로 하면.. 명령1|명령2 까지만 되게되네요..
명령1|명령2|명령3이어가려면 fork를 2번써야할거 같은데 으윽..

답변 해주신 feelpassion, jemiro, nthroot님 감사합니다..

nthroot의 이미지

waitpid() 하시면 문제가 있을텐데요.

limits.h에 보시면 PIPE_BUF 라고 있습니다.
pipe는 최대 PIPE_BUF 만큼만 입력할수 있고 출력에서 빠져나가면 빠져나간만큼 다시 입력할 수 있습니다.
입력pipe에서 PIPE_BUF 만큼 차버리면 비어질때까지 대기를 하게 되죠.
처음 프로세스에서 PIPE_BUF 보다 큰 사이즈를 써버리면 이 프로그램은 그대로 멈출것 같네요.

pipe는 pipe()로 생성된 p[0]과 p[1]를 공유할 수 있는곳이라면 어디서든지 사용가능합니다.

특히 부모/자식간에 pipe를 쓰는 이유는 일반적인 프로세스를 생성하는 경우 fork() 후 exe??() 함수를 사용하게 되는데..
이때 유일하게 존재하는 부모의 흔적이 fd이기 때문입니다. 나머지는 모두 자식 이미지로 대체 되구요.

------식은이 처------
길이 끝나는 저기엔 아무 것도 없어요. 희망이고 나발이고 아무 것도 없어.

댓글 달기

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