본문 바로가기
TIL/OS & Linux

MIT 6.828 - 1. Lab 01: Xv6 and Unix utilities - pingpong 코드 및 해석

by 왁왁s 2022. 11. 5.

MIT 6.828 - 1. Lab 01: Xv6 and Unix utilities - pingpong

 

문제 (Problems)

pingpong (easy)

Write a program that uses UNIX system calls to ''ping-pong'' a byte between two processes over a pair of pipes, one for each direction. The parent should send a byte to the child; the child should print "<pid>: received ping", where <pid> is its process ID, write the byte on the pipe to the parent, and exit; the parent should read the byte from the child, print "<pid>: received pong", and exit. Your solution should be in the file user/pingpong.c.

Some hints:

  • Use pipe to create a pipe.
  • Use fork to create a child.
  • Use read to read from a pipe, and write to write to a pipe.
  • Use getpid to find the process ID of the calling process.
  • Add the program to UPROGS in Makefile.
  • User programs on xv6 have a limited set of library functions available to them. You can see the list in user/user.h; the source (other than for system calls) is in user/ulib.c, user/printf.c, and user/umalloc.c.

Run the program from the xv6 shell and it should produce the following output:

    $ make qemu
    ...
    init: starting sh
    $ pingpong
    4: received ping
    3: received pong
    $
  

Your solution is correct if your program exchanges a byte between two processes and produces output as shown above.

 

 


 

코드(Code) - pingpong.c 파일

#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"

int main(int argc, char *argv[]) 
{
	int parent_fd[2], child_fd[2]; //parent, child file descriptor
	char get_buf[128]; //Receive pingpong message 
	
	pipe(parent_fd); //create pipe
	pipe(child_fd);
	
	if (fork() == 0) //child 
	{  
		close(parent_fd[1]);
		read(parent_fd[0], get_buf, 4); //read 4bytes
		close(parent_fd[0]);

		printf("%d: received %s\n", getpid(), get_buf);

		close(child_fd[0]);
		write(child_fd[1], "pong", 4);
		close(child_fd[1]);

	}
	else //parent
	{
		close(parent_fd[0]);
		write(parent_fd[1], "ping", 4);
		close(parent_fd[1]);

		close(child_fd[1]);
		read(child_fd[0], get_buf, 4); //read 4bytes
		close(child_fd[0]);
		printf("%d: received %s\n", getpid(), get_buf);
	}
	exit();
}

 


 

로직(logic) 설명

 

 

부모와  자식 프로세스의 파이프 file descriptor을 받기 위한 변수 parent_fdchild_fd를 생성하고, write값을 받기 위한 변수 get_buf를 생성한다.

 

 

pipe는 기본적으로 one-way 단방향 통신이기 때문에 pipe를 2개 생성함으로써 양방향 통신이 가능하도록 한다.

 

Pipe를 2개 생성한 후에 fork( )를 함으로써 자식 프로세스도 부모 프로세스의 pipe를 가지도록 한다. fork( ) == 0 일 때, 그러니까 자식프로세스일 때는 부모 프로세스가 읽고(read), 자식 프로세스가 쓰기(write)를 한다. 부모 프로세스가 읽을 때 부모가 쓰는 것을 방지하기 위해 close(parent_fd[1]); 을 해준다. 그리고 read가 끝나면 close(parent_fd[0]); 을 해주어 파이프를 닫는다. 자식 프로세스는 4bytes 만큼을 사용해 “pong”을 write한다.

 

마찬가지로 부모 프로세스일 때는 부모 프로세스가 “ping”을 4bytes만큼 write를 하고, 자식 프로세스는 get_buf에서 read를 한다.

이렇게 부모 프로세스와 자식 프로세스가 pipe 2개와 file descriptor 4개를 가지고 양방향 통신을 하는 pipe를 구현한다.

 

 


 

구현 결과(Result)

 

댓글