------------------------------------------------------------------------------------
참고: TCP/IP 소켓 프로그래밍
------------------------------------------------------------------------------------
1. 데몬 함수의 사용
: 프로세스를 데몬화 → 이 프로세스의 부모 프로세스는 init 프로세스가 되는데,
init 프로세스는 컴퓨터가 꺼지기 전에는 계속 수행되는 프로세스이므로
강제로 데몬 프로세스를 종료시키지 않는 한 계속적으로 백그라운드로 실행된다.
void makedaemon()
{
pid_t pid;
if((pid = fork()) < 0)
exit(0);
else if(pid != 0)
exit(0);
close(0);
close(1);
setsid();
}
2. IPC : 내부 프로세스 통신을 위한 모든 방법
1) PIPE(파이프)를 이용한 프로세스 간 통신
☞ 가장 오래된 기법 : 오랜 시간동안 사용되어 오면서 충분히 검증되었다.
☞ 파이프는 각 프로세스의 파일 디스크립터를 연결시켜 주는 것의 의미한다.
☞ 단점: 부모, 자식 프로세스의 데이터 통신을 위해서만 사용할 수 있다.
(다른 프로세스와의 통신 불가능)
☞ int pipe(int filedes[2]);
- 인자 : filedes[0]은 읽기 전용(입력), filedes[1]은 쓰기 전용(출력)이다.
- 반환값 : 성공할 때는 0을 반환하고, 실패하면 -1을 반환한다.
- 헤더 파일 : unistd.h
- 읽고(read) 쓸(write) 경우, read, write 함수를 사용하면 된다.
예) #include <sys/types. h>
#include <unistd. h>
#include <stdio. h>
#include <stdlib. h>
/* 파이프로부터 문자들을 읽고 그들은 표준 출력에 출력하라 */
void read_from_pipe (int file)
{
FILE *stream;
int c;
stream = fdopen (file, "r");
while ((c = fgetc (stream)) != EOF)
putchar (c);
fclose (stream);
}
/* 파이프에 어떤 텍스트를 써라 */
void write_to_pipe (int file)
{
FILE *stream;
stream = fdopen (file, "w");
fprintf (stream, "hello, world!\n");
fprintf (stream, "goodbye, world!\n");
fclose (stream);
}
int main (void)
{
pid_t pid;
int mypipe[2];
/* 파이프를 만들어라 */
if (pipe (mypipe))
{
fprintf (stderr, "Pipe failed. \n");
return EXIT_FAILURE;
}
/* 자식 프로세스를 만들어라 */
if ((pid = fork ()) == 0) /* 이것은 자식 프로세스이다. */
{
read_from_pipe (mypipe[0]);
return EXIT_SUCCESS;
}
else if (pid < 0) /* fork가 실패했다. */
{
fprintf (stderr, "Fork failed. \n");
return EXIT_FAILURE;
}
else /* 이것은 부모 프로세스이다. */
{
write_to_pipe (mypipe[1]);
return EXIT_SUCCESS;
}
}
2) FIFO(명명된 파이프)를 이용한 프로세스 간 통신
☞ 파이프의 단점을 해결하기 위해 만든 IPC 도구
☞ 파이프가 작자 불명의 통신 채널인 점에 비해 FIFO는 mkfifo를 호출함으로써 파일 시스템에 삽입된다.
☞ 큐(queue)와 같은 데이터 입출력 구조를 가진다.
☞ 파이프와는 달리 읽기와 쓰기를 동시에 할 수 있다. (하지만 보통 각각 따로 만든다.)
☞ int mkfifo(const char *pathname, mode_t mode);
- 인자 : pathname → 생성하고자 하는 FIFO 파일명, mode → FIFO 파일의 권한을 지정
- 반환값 : 성공하면 0을 반환하고, 에러가 발생한 경우에는 -1을 리턴한다.
- 헤더 파일 : sys/stat. h
- 읽고(read) 쓸(write) 경우, read, write 함수를 사용하면 된다.
예) fifo_server
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#define FIFO_READ "/tmp/fifo_c"
#define FIFO_WRITE "/tmp/fifo_s"
int main()
{
int fp_w;
int fp_r;
int i = 0;
umask(0000); // 파일 생성시 권한에 대한 마스크 설정
// mkfifo를 이용해서 FIFO파일을 생성한다.
// FIFO_READ는 클라이언트로 부터 데이터를 읽기 위해서
if (mkfifo(FIFO_READ, 0666) != 0)
{
perror("mkfifo failure");
}
// FIFO_WRITE는 클라이언트로 데이터를 쓰기 위해서 사용한다.
if (mkfifo(FIFO_WRITE, 0666) != 0)
{
perror("mkfifo failure");
}
if( (fp_r = open(FIFO_READ, O_RDWR)) < 0)
{
perror("open error : ");
exit(0);
}
if((fp_w = open(FIFO_WRITE, O_RDWR)) < 0)
{
perror("open error : ");
exit(0);
}
while(read(fp_r, (void *)&i, sizeof(int)) > 0)
{
printf("클라이언트로 부터 데이터 읽음 %d\n", i);
i = i*2;
write(fp_w, (void *)&i, sizeof(int));
}
exit(1);
}
예) fifo_client
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#define FIFO_WRITE "/tmp/fifo_c"
#define FIFO_READ "/tmp/fifo_s"
int main()
{
int fp_w;
int fp_r;
int i = 1;
if((fp_r = open(FIFO_READ, O_RDWR)) < 0)
{
perror("open error : ");
exit(0);
}
if((fp_w = open(FIFO_WRITE, O_RDWR)) < 0)
{
perror("open error : ");
exit(0);
}
while(1)
{
sleep(1);
write(fp_w, (void *)&i, sizeof(int));
read(fp_r, (void *)&i, sizeof(int));
printf("서버로 부터 데이터 읽음 %d\n", i);
}
exit(1);
}
------------------------------------------------------------------------------------
'IT_Programming > System Programming' 카테고리의 다른 글
[펌] 링커 스크립트 (0) | 2013.05.08 |
---|---|
[UNIX] 공유 메모리를 이용한 프로세스 간 통신(IPC) (0) | 2011.02.21 |
[펌] ARM Developer Suite(ADS) 1.2 에서 C 코드와 ASM 코드 섞어 쓰기 (0) | 2009.10.07 |
[펌] 리눅스에서 시리얼 제어 하기 (0) | 2009.09.30 |
GDB를 이용한 디버깅 (0) | 2009.05.26 |