이것은 한낱 대학생이 교수의 수업을 듣고 작성한 개인저장용 복습 문서입니다.
그렇지만, 물론 지적과 수정은 환영합니다.
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
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가 사라져도 그대로 존재한다.
'💻 CS > 시스템프로그래밍' 카테고리의 다른 글
[시스템프로그래밍] Times and Timers (0) | 2019.12.07 |
---|---|
[시스템프로그래밍] Signals (0) | 2019.12.06 |
[시스템프로그래밍] Files and Directories (0) | 2019.11.26 |
[시스템프로그래밍] UNIX I/O - 2 (0) | 2019.11.07 |
[시스템프로그래밍] UNIX I/O - 1 (2) | 2019.11.04 |