반응형

넌블록킹과 블록킹

분류기준 대기

블록킹 → 대기 , read하거나 write 할 때, 완료될 때까지 대기, 함수가 반환할 때, 성광과 실패를 알 수 있다.

넌블럭킹 → 대기 안함, 어떤 요청을 하면, 성공이든 실패든 일단 즉시 처리 후 반환한다. 함수가 반환되면 성공, 실패, 부분성공의 상태가 존재 가능

 

동기와 비동기

분류 기준은 순서

동기 → 순서대로 처리 보장

비동기 → 순서대로 처리를 보장하지 않음(out-of-order)

일반적인 시스템 프로그래밍의 입출력 함수는 모두 ‘동기’ 모델이다.

비동기식은 시그널, AIO, 스레드(Task 단위로는 비동기, Task 내의 기능들은 동기 → 스레드의 동기/비동기 여부는 기준 관점에 따라 다를 수 있다.)

반응형

시그널

시그널이란 소프트웨어 인터럽트이다.

프로세스에 뭔가 발생했음을 알리는 간단한 메시지를 비동기적으로 보내는 것을 의미한다.

 

시그널이 발생하는 경우는 다음과 같다.

0으로 나누기처럼 프로그램에서 예외적인 상황이 일어나는 경우나

Kill 함수처럼 시그널을 보낼 수 있는 함수를 사용해서 다른 프로세스에 시그널을 보내는 경우,

사용자가 CTRL+C와 같이 인터럽트 키를 입력한 경우가 존재한다.

 

 

시그널 처리방법

시그널이 프로세스에 도달하면 프로세슨느 각 시그널에 지정된 기본 동작을 수행한다.

대부분의 기본 동작은 프로세스를 종료하는 것이다.

하지만 프로그래밍을 통해 시그널을 무시하거나,

시그널 처리를 위한 함수(핸들러)를 지정할 수 있고

블럭처리를 할 수 있다.

 

 

시그널의 종류

시그널의 종류

 

시그널 보내기

kill -9 3255

kill -[시그널번호] PID

kill은 프로세스에 시그널을 보내는 명령어이다.

3255번 프로세스에 9번 시그널(SIGKILL)을 보내면 프로세스가 강제 종료 된다.

 

 

#include <sys/types.h>
#include <signal.h>

int kill(pid_t pid, int sig);
import os
import signal
os.kill(pid, sig) # signal.SIGALRM와 같이 시그널 변수를 사용한다.


os.killpg(pgid, sig) # 프로세스 그룹에 시그널을 보낼 때 사용한다.

 

pid > 0 인 경우 pid로 지정한 프로세스에 시그널을 발송한다.

pid < -1 일 때는 프로세스 그룹 ID가 pid의 절대값인 프로세스 그룹에 속하고

시그널을 보낼 권한을 가지고 있는 모든 프로세스에 시그널을 발송한다.

 

pid == 0 인 경우

특별한 프로세스를 제외하고 프로세스 그룹ID가 시그널을 보내는 프로세스의 프로세스 그룹 ID과 같은

모든 프로세스에게 시그널을 발송한다.

 

pid == -1 인 경우

시그널을 보내는 프로세스의 유효 사용자 ID가 root가 아니라면,

특별한 프로세스를 제외하고 프로세스의 실제 사용자ID가

시그널을 보내는 프로세스의 유효 사용자ID와 같은 모든 프로세스에 시그널을 발송한다.

 

#include <unistd.h>
#include <signal.h>
#include <stdio.h>

int main() {
    printf("Before SIGCONT Signal to parent.\n");

    kill(getppid(), SIGCONT);

    printf("Before SIGQUIT Signal to me.\n");

    kill(getpid(), SIGQUIT);

    printf("After SIGQUIT Signal.\n");
    
    return 0;
}
#결과

root@ac265c3fef72:/source/signal# ./ex8_1
Before SIGCONT Signal to parent.
Before SIGQUIT Signal to me.
Quit

SIGQUIT 시그널을 보내면 코어 덤프로 종료되는 것을 알 수 있다.

 

 

 

raise 함수를 이용하면 함수를 호출한 프로세스에 시그널을 발송한다.

// c
int raise(int sig);


//python
signal.raise_signal(signal)

 

abort함수를 이용하면 함수를 호출한 프로세스에 SIGABRT 시그널을 발송한다.

SIGABRT 시그널은 프로세스를 비정상적으로 종료 시키고 코어 덤프를 생성한다.

// c
void abort(void);

// python
os.abort()

 

 

시그널 핸들러

시그널 핸들러는 시그널을 받았을 때 이를 처리하기 위해 지정된 함수이다.

프로세스를 종료하기 전에 처리할 것이 있는 경우

특정 시그널에 대해 종료하고 싶지 않을 경우 지정하거나 (empty function)

특정 시그널에 다른 일을 하고 싶은 경우 지정한다. (do something function)

 

SIGKILL, SIGSTOP을 제외한 모든 시그널을 핸들러에 지정할 수 있다.

 

// c
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

// python
signal.signal(signalnum, handler)

 

handler는 sig로 지정한 시그널을 받았을 때 처리할 방법을 나타낸다.

사용자자 정의 시그널 핸들러 함수명을 이용한다.

SIG_IGN : 시그널을 무시하도록 지정한다.

SIG_DFL : 기본 처리 방법으로 처리하도록 지정한다.

 

실패시 SIG_ERR을 반환하고, 성공시 이전 핸들러를 반환한다.

 

signal 함수는 시스템 마다 다르게 동작하는데

system V 계열의 경우 시그널 핸들러를 한번 사용 하면 시그널 처리 방법을 기본 처리 방법(SIG_DFL)로 재설정한다.

시그널이 들어올 때마다 시그널 핸들러를 호출하려면 매번 시그널 핸들러를 재지정해야한다.

BSD 계열의 경우는 기본 처리 방법(SIG_DFL)로 재설정 하지 않고 계속 시그널 핸들러를 계속 사용하고,

리눅스 계열의 경우 커널의 signal(2) 시스템 콜은 시스템 V와 같은 방식으로 동작하고,

gcc의 glibc 2부터 signal(3) 함수는 signal(2)를 호출하지 않고 sigaction(2)를 호출해 BSD 형식으로 동작한다.

 

 

시그널 집합

시그널을 개별적으로 처리하지 않고 복수의 시그널을 처리하기 위해 도입한 개념이다.

POSIX에서 도입했다.

 

시그널 집합의 처리를 위한 구조체 sigset_t

typedef struct{
	unsigned int __sigbits[4];
} sigset_t;

시그널을 비트 마스크(128bit)로 표현한다. 각 비트가 특정 시그널과 1:1로 연결된다.

비트 값이 1이면 해당 시그널이 설정된 것이고, 0이면 시그널 설정이 안된 것이다.

 

 

시그널 처리 함수

//sigemptyset(3)을 활용하여 시그널 집합에서 모든 시그널을 0으로 설정할 수 있다.
int sigemptyset(sigset_t *set);

//시그널 집합에서 모든 시그널을 1로 설정
int sigfillset(sigset_t *set);

//시그널 집합에 시그널 설정 추가
int sigaddset(sigset_t *set, int signo);

//시그널 집합에 시그널 설정 삭제
int sigdelset(sigset_t *set, int signo);

//시그널 집합에서 시그널이 포함되어 있는지 확인
int sigismember(sigset_t *set, int signo);

 

#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>

int main() {
    sigset_t st;

    sigemptyset(&st);

    sigaddset(&st, SIGINT);
    sigaddset(&st, SIGQUIT);

    if(sigismember(&st, SIGINT))
        printf("SIGINT is setting.\n");

	//__val은 시스템 환경마다 다른 변수 이름을 사용해야한다 ubuntu에서는 __val 사용
    printf("** Bit Pattern: %x\n", st.__val[0]);

    return 0;
}

실행 결과

SIGINT is setting.
** Bit Pattern: 6

 

sigchild로 자식 프로세스 정리

#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>

static void sig_child(int);

int main() {
    pid_t pid;
    int i;
    signal(SIGCHLD, sig_child);

    pid = fork();
    
    //자식인 경우 pid가 0이므로 sleep후 종료한다
    if(pid == 0){
        sleep(1);
        exit(0);
    }
    while(1){
    //부모인 경우 계속 while문을 돈다.
        i = i;
        sleep(1);
    }
    return 0;
}


static void sig_child(int signo){
    pid_t pid; int status;
    
    //wait함수로 자식프로세스 종료를 기다린다.
    pid = wait(&status);
    
    printf("child %d finished\n %d", pid, status);
}

 

SIGFPE로 divide by zero 에러 처리

#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>

static void sig_fpe(int);

int main() {
    pid_t pid;
    int i;
    signal(SIGFPE, sig_fpe);

    i = i/0;
}


static void sig_fpe(int signo){
    pid_t pid; int status;
    printf("Divide by 0 Error\n");
    
    exit(1);
}

 

 

기타 시그널 처리 함수

// 시그널 정보 출력
// s에 지정한 문자열을 붙여 정보 출력
void psignal(int sig, const char *s);

//인자로 받은 시그널을 가리키는 이름을 문자열로 리턴
char *strsignal(int sig);

//시그널 블록킹과 해제
//인자로 받은 시그널을 시그널 마스크에 추가하거나 해제한다
int sighold(int sig);
int sigrelse(int sig);

 

 

#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>


void handler(int signo){
    char *s;
    s = strsignal(signo);
    printf(stdout, "Received Signal : %s\n", s);
}

int main() {
    if (sigset(SIGINT, handler) == SIG_ERR){
        perror("sigset");
        exit(1);
    }

    sighold(SIGINT);
    pause();

    return 0;
}

이 경우 CTRL+C로 SIGINT를 보내도 프로그램이 종료되지 않는다.

 

 

//시그널 집합 블록과 해제
int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);

how : 시그널을 블록할 것인지, 해제할 것인지 여부 결정 

SIG_BLOCK : set에 지정한 시그널 집합을 시그널 마스크에 추가

SIG_UNBLOCK : set에 지정한 시그널 집합을 시그널 마스크에서 제거

SIG_SETMASK : set에 지정한 시그널 집합으로 현재 시그널 마스크를 대체

 

set은 블록하거나 해제할 시그널 집합 주소를 의미하고, oset은 NULL 또는 이전 설정값을 저장한 시그널 집합 주소이다.

 

#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>


int main() {
    sigset_t new;

    sigemptyset(&new);
    //시그널 집합에 SIGINT, SIGQUIT 설정
    sigaddset(&new, SIGINT);
    sigaddset(&new, SIGQUIT);
    sigprocmask(SIG_BLOCK, &new, (sigset_t *) NULL);

    printf("Blocking Signals : SIGINT, SIGQUIT\n");
    printf("Send SIGQUIT\n");
    //SIGQUIT 시그널 보내기
    kill(getpid(), SIGQUIT);


    sleep(5);
    printf("UnBlocking Signals\n");

    //시그널 집합 블록 해제
    sigprocmask(SIG_UNBLOCK, &new, (sigset_t *) NULL);

    return 0;
}

위 코드처럼 시그널을 블록해두면 해당 시그널을 처리하지 않고 대기상태로 두었다가,

시그널 집합 블록을 해제하면 그때 대기해두었던 시그널들을 처리한다.

 

 

시그널 대기 함수

// 시그널 대기
//sig : 시그널이 올 때까지 대기할 시그널(1개)
int sigpause(int sig);

//set: 기다리려는 시그널을 지정한 시그널 집합
int sigsuspend(const sigset_t *set);

 

 

sigset(집합)과 sigsuspend 사용으로 시그널을 기다릴 수 있다.

#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>

void handler(int signo){
    psignal(signo, "Received Signal:");
}


int main() {
    sigset_t set;
    sigset(SIGQUIT, handler);

    sigfillset(&set);
    sigdelset(&set, SIGQUIT);

    printf("Wait...\n");

    sigsuspend(&set);


    return 0;
}
Wait...
^Z^X^C
^C
^C
^\Received Signal:: Quit

 

 

//시그널 기다리기
int sigwait(const sigset_t *set, int *sig)

set에 포함된 시그널만 기다리고, 다른 시그널은 블럭되지 않는다.

sig에는 시그널을 수신하였을 때, 수신한 시그널 번호를 저장한다.

 

#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>

void handler(int signo){
    psignal(signo, "Received Signal:");
}

int main() {
    sigset_t set;
    int sig;
    sigset(SIGQUIT, handler);

    sigfillset(&set);
    sigdelset(&set, SIGQUIT);

    printf("Wait...\n");

    //시그널이 올때까지 가디렸다가 다 처리한다.
    sigwait(&set, &sig);

    psignal(sig, "Continued by signal :");
    fflush(stdout);

    return 0;
}

 

시그널 보내기 sigsend

int sigsend(idtype_t idtype, id_t id, int sig);

idtype은 id에 지정한 값의 종류, id는 시그널을 받을 프로세스나 프로세스 그룹, sig는 보내려는 시그널을 의미한다.

 

sigsend idtype

시그널 무시처리 sigignore

int sigignore(int sig);

인자로 지정한 시그널의 처리방법을 SIG_IGN으로 설정한다.

 

 

 

 

SIGNAL 함수 호환성

svr4 시스템과 BSD 시스템 간의 동작이 다르다.

앞으로 개발할 때는 이식성을 고려하여 signal을 사용하지 말고 sigaction을 사용한다.

 

 

시그널과 프로그램 시작

프로세스가 fork될 때

자식 프로세스는 부모 프로세스의 시그널 처리를 상속한다.

 

프로그램이 exec될 때는

기본 동작이 정의된 모든 시그널은 기본 동작으로 변경하고,

기본 동작이 없는 시그널은 그대로 둔다.

 

대화형 쉘(Interactive Shell)에서 실행하는 경우

백그라운드 프로세스는 인터럽트 및 종료 신호의 처리를 무시하도록 설정하고

많은 대화형 프로그램은

백그라운드에 있지 않을 때만 신호를 포착한다.

int sig_int(), sig_quit()

if(signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, sig_int);
if(signal(SIGQUIT, SIG_IGN) != SIG_IGN) signal(SIGQUIT, sig_quit);

 

반응형

posix shm_open

저수준 open 함수와 같은 원형이다.

기존의 유닉스 파일 처리 개념을 확장하고, name은 항상 / 로 시작한다.

메모리의 일부를 파티션 공간처럼 만들고, 여기에 파일을 만들어 공유하는 방식이다.

 

int shm_open(const char *name, int oflag, mode_t mode);
int shm_unlink(const char *name)

삭제는 shm_unlink(const char *name)을 활용한다.

posix 공유메모리에는 디렉토리 개념이 존재하지 않기 때문에 name에 슬래시를 붙이면 안된다.

 

그리고 posix 공유 메모리는 리얼타임 라이브러리를 활용하기 때문에

컴파일 시에 rt 라이브러리를 링크해야 정상적으로 컴파일이 가능하다.

gcc -o source source.c -lrt

 

open과 shm_open 차이

open은 disk 파일 시스템의 파일을 이용하여 공유하고

shm_open은 메모리의 일부를 파일 시스템으로 표현한 /dev/shm에서 파일 개념을 표현한다.

 

#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/fcntl.h>
#include <stdlib.h>
#include <stdio.h>

int main() {
    int fd, pagesize, length;
    caddr_t addr;
    pagesize = sysconf(_SC_PAGESIZE);
    length = 1 * pagesize;

    //m.dat 앞에 슬래시를 붙이면 안된다. posix 공유메모리에는 디렉토리가 존재하지 않기 때문이다.
    if ((fd = shm_open("m.dat", O_RDWR | O_CREAT | O_TRUNC, 0666)) == -1) {
        perror("shm_odsafpen");
        exit(1);
    }

    if (ftruncate(fd, (off_t) length) == -1) {
        perror("ftruncate");
        exit(1);
    }

    addr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t) 0);
    if (addr == MAP_FAILED) {
        perror("mmap");
        exit(1);
    }

    close(fd);
    strcpy(addr, "Ftruncate Test\n");


    return 0;
}

위 코드에서 파일 디스크립터인 fd를 close 하여도

addr에 해당 공유 메모리의 주소가 남아있기 때문에 strcpy를 활용하여 매핑한 메모리에 데이터를 정상적으로 쓰는 게 가능하다.

 

 

POSIX 공유 메모리의 삭제

공유 메모리를 삭제할 때는 shm_unlink를 이용하면 된다.

파일을 삭제하는 unlink와 동일한 구조이다.

 

만약 위의 코드처럼 mmap으로 공유 메모리의 주소를 맵핑하고 있다면

munmap으로 맵핑을 해제 한뒤 unlink로 파일을 삭제해야 한다.

 

만약 posix 공유메모리를 사용 중에 삭제하는 경우에는

리눅스에서는 새로운 프로세스는 공유 메모리에 연결이 불가능하고,

기존 프로세스들은 공유 상태를 유지하게 된다. 이는 표준안에는 명시되지 않은 현상이다.

 

 

 


 

 

POSIX 세마포어

posix 세마포어는 외부에서 접근 가능한 인터페이스 경로 유무에 따라

명명된 세마포어(named semaphore), 익명 세마포어(nameless/anonymous semaphore)로 구분된다.

 

 

익명 세마포어 생성

#include <semaphore.h>

int sem_init(sem_t *sem, int pshared, unsigned int value);

sem에는 생성된 posix 세마포어를 저장한다.

pshared에는 현재 프로세스에서만 사용할 때는 0을 두고, 여러 프로세스에서 공유를 목적으로 생성할 때는 0이 아닌 값을 둔다.

value는 초기화할 세모포어의 값으로 리소스의 수를 의미한다.

 

 

명명된 세마포어 생성

#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>

sem_t *sem_open(const char *name, int oflag);
sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);

저수준 open함수와 유사하고 결과로 세마포어를 얻는다. name은 항상 / 로 시작한다

value에는 익명 세마포어와 동일하게 초기화할 세마포어의 값으로 리소스의 수를 둔다.

 

생성된 세마포어는 /dev/shm/ 의 경로에 생성된다.

posix 공유 메모리 처럼 "/m.sem" 파일을 sem_open 하면,

/dev/shm/sem.m.set 파일이 생성된다.

 

oflag에는 O_CREATE와 O_EXCL이 사용 가능하다.

실패 시에는 SEM_FAILED를 반환한다.

 

 

posix 세마포어는 스레드 라이브러리를 사용하여 컴파일 할때 링크를 해주어야한다.

gcc -o source source.c -pthread

 

 

posix 세마포어 연산 : P

#include <semaphore.h>

int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);

//timespec
struct timepec{
	time_t tv_sec;
    long tv_nsec;
};

posix 세마포어는 한 번에 -1씩만 가능하다. 리소스가 없는 경우(value == 0)이면 대기한다.

 

sem_wait는 리소스가 없으면 대기하고,

sem_trywait는 리소스가 없으면 에러를 반환하고, errno에 EAGAIN이 설정된다.

sem_timedwait는 리소스가 없으면 지정한 시간만큼 대기하고, 대기 이후에도 없으면 에러를 반환하고,

errno에 ETIMEOUT이 설정된다.

 

sem_timedwait는 UNIX 시간 표현으로 절대시간을 이용한다. 10초 대기를 하려면 현재 시간에 +10초를 해야 한다.

struct timespec ts_timeout;
ts_timeout.tv_sec = time(NULL) + 10;
ts_timeout.tv_nsec = 0;

if(sem_timedwait(psem, &ts_timeout) == -1){
	if(errno = ETIMEOUT){ /* handle timeout */}
	else { /* Otherwise */ }
}

 

posix 세마포어 연산 : V

세마포어에서 V 연산은 리소스를 +1 한다. 대기하는 경우는 없다. 실패하는 경우는

최대값(SEM_VALUE_MAX)보다 커지는 경우로, errno에 EOVERFLOW가 설정된다.

int sem_post(sem_t *sem)

 

 

 

posix 세마포어의 제거

익명 세마포어를 제거할 때는 sem_destroy를 사용한다.

프로세스가 종료되면 자연스럽게 세마포어가 해제되고, 직접 제거하고자 하는 경우에 사용한다.

int sem_destroy(sem_t *sem);

 

명명된 세마포어를 제거할 때는 sem_close, sem_unlink를 사용한다.

int sem_close(sem_t *sem);
int sem_unlink(const char *name);

 

sem_open에 대응하는 sem_close를 통해 닫는다.

생성된 세마포어 파일을 삭제하기 위해 sem_unlink를 사용한다.

반응형
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    char *fname;
    char fntmp[BUFSIZ];
    char template[32];

    fname = tmpnam(NULL);
    printf("1. TMP File Name(tmpnam) : %s\n", fname);

    tmpnam(fntmp);
    printf("2. TMP File Name(tmpnam) : %s\n", fntmp);

    fname = tempnam("/tmp", "hanbit");
    printf("3. TMP File Name(tempnam) : %s\n", fname);

    strcpy(template, "/tmp/hanbitXXXXXX");
    fname = mktemp(template);
    printf("4. TMP File Name(mktemp) : %s\n", fname);


    return 0;
}

결과

반응형

1. Server

#include <stdio.h>
#include <unistd.h>
#include <sys/times.h>
#include <limits.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>

int main() {
    int pd, n;
    char msg[] = "Hello, FIFO";

    printf("Server =====\n");

    if(mkfifo("./HAN-FIFO", 0666) == -1){
        perror("mkfifo");
        exit(1);
    }

    if((pd = open("./HAN-FIFO", O_WRONLY)) == -1){
        perror("open");
        exit(1);
    }


    printf("To Client : %s\n", msg);

    n = write(pd, msg, strlen(msg)+1);
    if(n==-1){
        perror("write");
        exit(1);
    }
    close(pd);





    return 0;
}

2. client

#include <stdio.h>
#include <unistd.h>
#include <sys/times.h>
#include <limits.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>

int main() {
    int pd, n;
    char inmsg[80];

    if((pd = open("./HAN-FIFO", O_RDONLY)) == -1){
        perror("open");
        exit(1);
    }

    printf("Client ====\n");
    write(1, "From Server :", 13);

    while((n=read(pd, inmsg, 80)) > 0)
        write(1, inmsg, n);

    if(n==-1){
        perror("read");
        exit(1);
    }

    write(1, "\n", 1);
    close(pd);

    return 0;
}
반응형
#include <stdio.h>
#include <unistd.h>
#include <sys/times.h>
#include <limits.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>

int main() {
    int fd1[2], fd2[2];
    pid_t pid;
    char buf[257];
    int len, status;

    if(pipe(fd1)== -1){
        perror("pipe");
        exit(1);
    }


    if(pipe(fd2)==-1){
        perror("pipe");
        exit(1);
    }

    switch(pid = fork()){
        case -1 :
            perror("fork");
            exit(1);
            break;

        case 0:
            close(fd1[1]);
            close(fd2[0]);
            write(1, "Child Process:", 15);
            len = read(fd1[0], buf, 256);
            write(1, buf, len);

            strcpy(buf, "Good\n");
            write(fd2[1], buf, strlen(buf));
            break;
        default:
            close(fd1[0]);
            close(fd2[1]);
            buf[0] = '\0';
            write(fd1[1], "Hello\n", 6);

            write(1, "Parent Process:", 15);
            len = read(fd2[0], buf, 256);
            write(1, buf, len);
            waitpid(pid, &status, 0);
            break;
    }

    return 0;
}
반응형
#include <stdio.h>
#include <unistd.h>
#include <sys/times.h>
#include <limits.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>

int main() {
    pid_t pid;
    int status;

    switch(pid = fork()){
        case -1 :
            perror("fork");
            exit(1);
            break;
        case 0:
            printf("--> Child Process\n");
            exit(3);
            break;
        default:
            while(wait(&status) != pid)
                continue;
            printf("--> Parent process - My PID:%d\n", (int)getpid());
            printf("Status: %d, %x\n, status, status");
            //자식프로세스의 종료 상태값을 알 수 있다.
            printf("Child process Exit status:%d\n", status >> 8);
            break;
    }

    return 0;
}

 

반응형
#include <stdio.h>
#include <unistd.h>
#include <sys/times.h>
#include <limits.h>
#include <stdlib.h>
#include <time.h>

int main() {
    pid_t pid;

    switch(pid = fork()){
        case -1 :
            perror("fork");
            exit(1);
            break;
        case 0:
            printf("--> Child Process\n");
            if(execlp("ls", "ls", "-a", (char *)NULL) == -1){
                perror("exelcp");
                exit(1);
            }
            exit(0);
            break;
        default:
            printf("--> Parent process - My PID:%d\n", (int)getpid());
            break;
    }
    
    return 0;
}

 

+ Recent posts