[회고] 신입 iOS 개발자가 되기까지 feat. 카카오 자세히보기

💻 CS/시스템프로그래밍

[시스템프로그래밍] UNIX Special Files

inu 2019. 12. 1. 16:47
반응형

이것은 한낱 대학생이 교수의 수업을 듣고 작성한 개인저장용 복습 문서입니다.

 

그렇지만, 물론 지적과 수정은 환영합니다.


Pipe

 

-서로 협력하는 능력은 프로세스에 있어서 필수적이다.

-가장 간단한 프로세스간 통신 방법은 pipe이다.

-동일한 시스템에서 실행되는 프로세스가 정보를 공유하도록 한다.

 

#include  <unistd.h>
int pipe(int fd[2]); 

-2개의 file descriptor의 배열을 파라미터로 활용한다.

-해당 파일의 [0]은 읽기전용이고, [1]은 쓰기전용이다.

-즉, [1]의 내용이 파이프라는 special file을 통해 [0]으로 가는 것이다.

-내용은 FIFO(first in first out) 방식으로 이동한다.

-pipe는 보통 이름이 없다.

-성공하면 파이프는 0을 리턴하고, 실패하면 -1을 리턴한다.

 

(특징)

-이름이 없어 두개의 file descriptor로만 접근할 수 있다.

-이러한 이유로 파이프를 만든 시스템 혹은 그 하위 시스템만 이를 사용할 수 있다.

-POSIX 자체적으로 [0]에 쓰거나 [1]로부터 읽어오는 것을 정의하고 있지 않다.

 

-프로세스가 파이프에 read를 요청하면, 파이프가 비어있지 않다면 곧바로 리턴한다.

-파이프가 비어있고 쓰기용 file descriptor가 open되어 있는경우 무언가 쓰여질때까지 읽기를 반복한다.

-만약 쓰기용 file descriptor가 열려있지 않다면 그냥 바로 0을 리턴한다.

(쓰기용이 close 되면 바로 0으로 리턴된다.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
main()
{
    int pipefd[2];
    int i;
    char s[1000];
    char *s2;
    if (pipe(pipefd) < 0) {
        perror("pipe");
        exit(1);
    }
    s2 = "Rex Morgan MD";
    write(pipefd[1], s2, strlen(s2));
    i = read(pipefd[0], s, 1000);
    s[i] = '\0';
    printf("Read %d bytes from the pipe: %s'\n", i, s);
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

- pipe함수가 음수를 리턴한다면 바로 종료

- s2의 내용을 [1]에 넣고

- 이를 [0]에 써준다.

- 이것이 파이프의 종합적인 원리

 

- 처음 pipe()함수를 설정할 때 두개의 file descriptor, [0]과 [1]을 설정한다.

- [1]에 무엇이든 쓰여있다면 [0]으로 읽을 수 있다.
- 한번 write를 해놓으면 다른 프로세스에서 read()를 하기 전까지 계속 해당 내용을 버퍼에 보유한다.

\

- 하지만 하나의 프로세스에서 파이프를 사용하는 것은 크게 의미있는 행위가 아니다. 따라서, 부모 자식관계에서 주로 쓰인다.

- 자식은 file descriptor table을 공유하기 때문에 파이프를 함께 사용할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#define BUFSIZE 10
int main(void) {
    char bufin[BUFSIZE] = "empty";
    char bufout[] = "hello";
    int bytesin;
    pid_t childpid;
    int fd[2];
    if (pipe(fd) == -1) {
        perror("Failed to
            create the pipe");
            return 1;
    }
    bytesin = strlen(bufin);
    childpid = fork();
    if (childpid == -1) {
        perror("Failed to fork");
        return 1;
    }
    if (childpid) /* parent code */
        write(fd[1], bufout, strlen(bufout));
    else /* child code */
        bytesin = read(fd[0], bufin, BUFSIZE);
    fprintf(stderr, "[%ld]:my bufin is {%.*s},
        my bufout is{ %s }\n",
        (long)getpid(), bytesin, bufin, bufout);
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 


- 자식 프로세스는 문자열을 무조건 성공적으로 읽어들이는가?

- No. 100퍼센트 입력되지 않을 수 있다. ("helty"정도를 읽어들일 수도 있다.)


FIFO

- 원래 파이프와 다르게 이름이 있고, 각 프로세스들이 종료되어도 남아있다.

- 일반 파일처럼 이름이 있다.

- permission이 있는 파일만 접근할 수 있다.

- permission만 있다면 어떤 프로세스든 접근할 수 있다.

 

#include <sys/stat.h>
int mkfifo(const char *path, mode_t mode); 

-path : 파이프의 이름 지정 (실행 경로)

-mode : permission 지정

-shell에서도 mkfifo라고 하는 것이 있어 shell에서도 만들수 있고, 프로그램 코드내에서도 만들수 있다.

-permernant한 파일이기 때문에 따로 삭제를 해주어야한다.

-shell에서 rm으로 삭제하거나 프로그램 코드에서 unlink하여 해당 파이프 삭제가능

 

#define FIFO_PERMS (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
if (mkfifo(“myfifo”, FIFO_PERMS) == -1)
perror(“Failed to create myfifo”);

- 유저만 write하고 모두가 read할 수 있는 fifo생성

 

if (unlink(“myfifo”) == -1)
perror(“Failed to remove myfifo”);

- fifo 삭제

 


1. fifo를 생성하고
2. 자식을 생성한다음
3. 자식이 fifo에 글을 쓰고
4. 부모가 그를 받아오는 구조
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <errno.h>
#include <fcntl.h>  
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#define BUFSIZE 256
#define FIFO_PERM  (S_IRUSR | S_IWUSR)
 
int dofifochild(const char *fifoname, const char *idstring);
int dofifoparent(const char *fifoname);
 
int main (int argc, char *argv[]) {
   pid_t childpid; 
 
   if (argc != 2) {                           /* command line has pipe name */
      fprintf(stderr, "Usage: %s pipename\n", argv[0]);
      return 1
   }
   if (mkfifo(argv[1], FIFO_PERM) == -1) {           /* create a named pipe */
      if (errno != EEXIST) {
         fprintf(stderr, "[%ld]:failed to create named pipe %s: %s\n"
              (long)getpid(), argv[1], strerror(errno));
         return 1
      }
   }
   if ((childpid = fork()) == -1){
      perror("Failed to fork");
      return 1;
   } 
   if (childpid == 0)                                   /* The child writes */
      return dofifochild(argv[1], "this was written by the child");
   else
      return dofifoparent(argv[1]);
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <errno.h>
#include <fcntl.h>  
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include "restart.h"
#define BUFSIZE 256
 
int dofifochild(const char *fifoname, const char *idstring) {
   char buf[BUFSIZE];
   int fd;
   int rval;
   ssize_t strsize;
 
   fprintf(stderr, "[%ld]:(child) about to open FIFO %s...\n",
          (long)getpid(), fifoname);
   while (((fd = open(fifoname, O_WRONLY)) == -1&& (errno == EINTR)) ; 
   if (fd == -1) {
      fprintf(stderr, "[%ld]:failed to open named pipe %s for write: %s\n"
             (long)getpid(), fifoname, strerror(errno));
      return 1
   } 
   rval = snprintf(buf, BUFSIZE, "[%ld]:%s\n", (long)getpid(), idstring);
   if (rval < 0) {
      fprintf(stderr, "[%ld]:failed to make the string:\n", (long)getpid());
      return 1
   } 
   strsize = strlen(buf) + 1;
   fprintf(stderr, "[%ld]:about to write...\n", (long)getpid());
   rval = r_write(fd, buf, strsize);
   if (rval != strsize) {
      fprintf(stderr, "[%ld]:failed to write to pipe: %s\n",
             (long)getpid(), strerror(errno));
      return 1;
   }
   fprintf(stderr, "[%ld]:finishing...\n", (long)getpid());
   return 0;
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <errno.h>
#include <fcntl.h>  
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include "restart.h"
#define BUFSIZE 256
#define FIFO_MODES O_RDONLY
 
int dofifoparent(const char *fifoname) {
   char buf[BUFSIZE];
   int fd;
   int rval;
 
   fprintf(stderr, "[%ld]:(parent) about to open FIFO %s...\n",
                       (long)getpid(), fifoname);
   while (((fd = open(fifoname, FIFO_MODES)) == -1&& (errno == EINTR))  ; 
   if (fd == -1) {
      fprintf(stderr, "[%ld]:failed to open named pipe %s for read: %s\n",
             (long)getpid(), fifoname, strerror(errno));    
      return 1
   }    
   fprintf(stderr, "[%ld]:about to read...\n", (long)getpid());
   rval = r_read(fd, buf, BUFSIZE);
   if (rval == -1) {
      fprintf(stderr, "[%ld]:failed to read from pipe: %s\n",
             (long)getpid(), strerror(errno));    
      return 1
   }    
   fprintf(stderr, "[%ld]:read %.*s\n", (long)getpid(), rval, buf);
   return 0
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

- FIFO는 연결되어 있던 file descriptor가 사라져도 그대로 존재한다.

반응형