프로세스 통신관련 샘플을 C언어로 짜 봤다.
실행방법은 제일 먼저 데몬을 띄워놓고 다른 프로세스가 뜬 다음에 “start”파라미터를 추가하여 실행하면 프로세스간에 숫자를 하나씩 증가하는 소스이다. 이 소스도 2곳에 문제가 있다. start를 여러곳에서 실행하면 중복으로 그값을 전달한다. 그리고 실행중인 프로세스가 죽으면 그 프로세스의 파이프에 값을 전달하지 못해 중단된다.
cc -o count count.c
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MSG_SIZE 80
#define PN "./named_pipe_file"
#define PIPE_SIZE 10
#define PIPE_NAME_SIZE 100
int sendData();
int createNumPipe();
int getPipeNo();
int getPipeCnt();
int main(int argc, char *argv[]) {
char msg[MSG_SIZE];
int fd, fdn;
int nread, rc;
int cnt = 1;
int pipeNo=0;
char myPipeNm[PIPE_NAME_SIZE] = {0x00, };
if (argc == 2) {
if (!strcmp("daemon", argv[1])) {
createNumPipe();
return 0;
}
}
pipeNo = getPipeNo();
if (pipeNo < 0) return -1;
sprintf(myPipeNm, "named_pipe_%d", pipeNo);
printf("my pipe name is %s\n", myPipeNm);
fflush(stdout);
if (argc == 2) {
// 이미 실행중인 경우 중복으로 여러개가 동작함.
if (!strcmp("start", argv[1])) sendData(pipeNo, cnt);
}
/* 기존에 named pipe가 있으면 삭제 */
if (access(myPipeNm,F_OK) == 0) {
unlink(myPipeNm);
}
/* named pipe 생성하기 */
if ((rc = mkfifo(myPipeNm,0666)) < 0) {
printf("fail to make named pipe\n");
return 0;
}
/* named pipe 열기, Read Write가능 해야 한다 */
if ((fd = open(myPipeNm, O_RDONLY)) < 0) {
printf("fail to open named pipe:%s\n", myPipeNm);
return 0;
}
while (1) {
msg[0] = '\0';
if ((nread = read(fd, msg, sizeof(msg))) < 0 ) {
printf("fail to call read()\n");
return 0;
}
if (strlen(msg) < 1) continue;
// 자료 수신후 5초후에 1을 더해서 보낸다.
printf("received : %s\t", msg);fflush(stdout);
sleep(5);
cnt = atoi(msg) + 1;
sendData(pipeNo, cnt);
}
close(fd);
return 0;
}
// 데이터 보내기
int sendData(int pipeNo, int cnt) {
char msg[MSG_SIZE];
int fd;
int nread, i;
char otherPipeNm[PIPE_NAME_SIZE] = {0x00, };
int pipeCnt=0;
int nextNo=0;
pipeCnt = getPipeCnt();
if (pipeCnt < 0) return -1;
nextNo = (pipeNo + 1) % pipeCnt;
sprintf(otherPipeNm, "named_pipe_%d", nextNo);
/* named pipe 열기, Write 전용으로 열기 */
if ((fd = open(otherPipeNm, O_WRONLY)) < 0) {
printf("fail to open named pipe:%s\n", otherPipeNm);
return 0;
}
/* Data를 보낸다. */
snprintf(msg, sizeof(msg), "%d", cnt);
if ((nread = write(fd, msg, sizeof(msg))) < 0 ) {
printf("fail to call write()\n");
return 0;
}
printf("send %s to %s\n", msg, otherPipeNm);
close(fd);
return 0;
}
/* num pipe 생성하기*/
int createNumPipe() {
char msg[MSG_SIZE];
int fd;
int nread, i, rc;
int pipeCnt=0;
/* 기존에 named pipe가 있으면 삭제 */
if (access(PN, F_OK) == 0) {
unlink(PN);
}
/* named pipe 생성하기 */
if ((rc = mkfifo(PN,0666)) < 0) {
printf("fail to make named pipe:%s\n", PN);
return 0;
}
if ((fd = open(PN, O_RDWR)) < 0) {
printf("fail to open named pipe:%s\n", PN);
return 0;
}
snprintf(msg, sizeof(msg), "%d", pipeCnt);
if ((nread = write(fd, msg, sizeof(msg))) < 0 ) {
return 0;
}
while(1) {
// max값을 가져오고 다시 max를 적어준다
if ((nread = read(fd, msg, sizeof(msg))) < 0 ) {
printf("fail to call read()\n");
return -1;
}
if ((nread = write(fd, msg, sizeof(msg))) < 0 ) {
return 0;
}
if (strlen(msg) < 1) continue;
if (pipeCnt == atoi(msg)) continue;
pipeCnt = atoi(msg);
printf("%d.", (pipeCnt -1));fflush(stdout);
sleep(1);
}
close(fd);
return 0;
}
/* pipe no 가져오기*/
int getPipeNo() {
char msg[MSG_SIZE];
int fd;
int nread, i, rc;
int pipeNo = 0;
if (access(PN, F_OK) != 0) {
printf("The pipe not found:%s\n", PN);
createNumPipe();
}
if ((fd = open(PN, O_RDWR)) < 0) {
printf("fail to open named pipe:%s\n", PN);
return -1;
}
if ((nread = read(fd, msg, sizeof(msg))) < 0 ) {
printf("fail to call read()\n"); fflush(stdout);
return -1;
}
pipeNo = atoi(msg);
snprintf(msg, sizeof(msg), "%d", pipeNo + 1);
if ((nread = write(fd, msg, sizeof(msg))) < 0 ) {
printf("write error!\n");
return 0;
}
close(fd);
return pipeNo;
}
/* pipe 갯수 가져오기*/
int getPipeCnt() {
char msg[MSG_SIZE];
int fd;
int nread, i;
int pipeCnt = 0;
if ((fd = open(PN, O_RDWR)) < 0) {
printf("fail to open named pipe\n");
return -1;
}
// max값을 가져오고 다시 max를 적어준다
if ((nread = read(fd, msg, sizeof(msg))) < 0 ) {
printf("fail to call read()\n");
return -1;
}
if ((nread = write(fd, msg, sizeof(msg))) < 0 ) {
return 0;
}
close(fd);
pipeCnt = atoi(msg);
return pipeCnt;
}
