본문 바로가기

C Language

access, dup, dup2, execve, fork, pipe, unlink, wait, waitpid, perror, strerror 함수 설명

C 언어에서 사용되는 주요 시스템 호출 함수들에 대해 상세히 설명하겠습니다.

## access()

`access()` 함수는 파일이나 디렉토리에 대한 접근 권한을 확인하는 데 사용됩니다.

```c
int access(const char *pathname, int mode);
```

- `pathname`: 접근 권한을 확인할 파일 또는 디렉토리의 경로
- `mode`: 확인할 접근 모드 (R_OK, W_OK, X_OK, F_OK)

 

access 함수에서 두 번째 인자는 파일이나 디렉토리에 대한 접근 권한을 확인하기 위해 사용되는 모드 플래그입니다. 이 플래그는 특정 권한을 나타내는 상수로 정의되어 있으며, 각각의 상수는 특정한 정수 값을 가집니다. 다음은 access 함수에서 사용되는 주요 상수와 그 숫자 값에 대한 설명입니다.

주요 상수 및 숫자 값

  • F_OK: 파일의 존재 여부를 확인합니다. 이 상수는 일반적으로 0으로 정의됩니다.
  • R_OK: 파일에 대한 읽기 권한을 확인합니다. 이 상수는 일반적으로 4로 정의됩니다.
  • W_OK: 파일에 대한 쓰기 권한을 확인합니다. 이 상수는 일반적으로 2로 정의됩니다.
  • X_OK: 파일에 대한 실행 권한을 확인합니다. 이 상수는 일반적으로 1로 정의됩니다.

이러한 상수는 비트 연산을 통해 조합하여 사용할 수 있습니다. 예를 들어, 읽기 및 쓰기 권한을 동시에 확인하고 싶다면 R_OK | W_OK를 사용하여 6(4 + 2)으로 표현할 수 있습니다.

결론

access 함수의 두 번째 인자는 파일 접근 권한을 확인하기 위한 상수로, 각 상수는 특정한 숫자 값으로 정의됩니다. 이 상수들은 비트 연산을 통해 조합하여 사용할 수 있으며, 이를 통해 다양한 접근 권한을 동시에 확인할 수 있습니다.


주요 특징:
- 실제 사용자 ID와 그룹 ID를 사용하여 권한을 확인합니다.
- 반환값: 성공 시 0, 실패 시 -1
- 주로 파일 존재 여부나 읽기/쓰기/실행 권한 확인에 사용됩니다.

## dup()

`dup()` 함수는 기존 파일 디스크립터의 복사본을 생성합니다.

```c
int dup(int oldfd);
```

- `oldfd`: 복제할 파일 디스크립터

주요 특징:
- 새로운 파일 디스크립터는 사용 가능한 가장 낮은 번호를 가집니다.
- 원본과 복사본은 동일한 파일 테이블 엔트리를 공유합니다.
- 반환값: 성공 시 새 파일 디스크립터, 실패 시 -1

## dup2()

`dup2()` 함수는 지정된 파일 디스크립터로 복제본을 생성합니다.

```c
int dup2(int oldfd, int newfd);
```

- `oldfd`: 복제할 파일 디스크립터
- `newfd`: 새로운 파일 디스크립터 번호

주요 특징:
- `newfd`가 이미 열려있으면 자동으로 닫힙니다.
- `oldfd`와 `newfd`가 같으면 아무 작업도 하지 않고 `newfd`를 반환합니다.
- 주로 표준 입출력을 리다이렉션하는 데 사용됩니다.

## execve()

`execve()` 함수는 현재 프로세스를 새로운 프로그램으로 대체합니다.

```c
int execve(const char *pathname, char *const argv[], char *const envp[]);
```

- `pathname`: 실행할 프로그램의 경로
- `argv`: 프로그램에 전달할 인자 배열
- `envp`: 환경 변수 배열

주요 특징:
- 성공 시 호출한 프로세스의 메모리 이미지를 완전히 새로운 프로그램으로 대체합니다.
- 실패 시에만 반환값이 있으며, 성공 시에는 반환하지 않습니다.
- 주로 `fork()` 후에 사용되어 새로운 프로그램을 실행합니다.

## fork()

`fork()` 함수는 현재 프로세스의 복사본인 새로운 자식 프로세스를 생성합니다.

```c
pid_t fork(void);
```

주요 특징:
- 부모 프로세스에는 자식 프로세스의 PID를 반환합니다.
- 자식 프로세스에는 0을 반환합니다.
- 실패 시 -1을 반환합니다.
- 자식 프로세스는 부모의 메모리 이미지를 그대로 복사합니다.

## pipe()

`pipe()` 함수는 프로세스 간 통신을 위한 파이프를 생성합니다.

```c
int pipe(int pipefd[2]);
```

- `pipefd`: 읽기 전용 파일 디스크립터
- `pipefd[1]`: 쓰기 전용 파일 디스크립터

주요 특징:
- 단방향 통신 채널을 생성합니다.
- 주로 부모-자식 프로세스 간 또는 형제 프로세스 간 통신에 사용됩니다.
- 성공 시 0, 실패 시 -1을 반환합니다.

## unlink()

`unlink()` 함수는 파일 시스템에서 파일의 링크를 제거합니다.

```c
int unlink(const char *pathname);
```

- `pathname`: 제거할 파일의 경로

주요 특징:
- 파일의 링크 카운트를 감소시킵니다.
- 링크 카운트가 0이 되면 파일이 삭제됩니다.
- 열려있는 파일 디스크립터에는 영향을 주지 않습니다.
- 성공 시 0, 실패 시 -1을 반환합니다.

## wait()

`wait()` 함수는 자식 프로세스가 종료될 때까지 부모 프로세스를 대기시킵니다.

```c
pid_t wait(int *wstatus);
```

- `wstatus`: 자식 프로세스의 종료 상태를 저장할 포인터

주요 특징:
- 자식 프로세스가 종료될 때까지 부모 프로세스를 블록합니다.
- 종료된 자식 프로세스의 PID를 반환합니다.
- 자식 프로세스의 종료 상태를 `wstatus`를 통해 얻을 수 있습니다.

## waitpid()

`waitpid()` 함수는 특정 자식 프로세스의 상태 변화를 기다립니다.

```c
pid_t waitpid(pid_t pid, int *wstatus, int options);
```

- `pid`: 기다릴 자식 프로세스의 PID
- `wstatus`: 자식 프로세스의 상태를 저장할 포인터
- `options`: 대기 옵션 (WNOHANG, WUNTRACED 등)

주요 특징:
- 특정 자식 프로세스를 기다리거나 모든 자식 프로세스를 기다릴 수 있습니다.
- 비차단 대기가 가능합니다 (WNOHANG 옵션 사용).
- 자식 프로세스의 상태 변화를 더 세밀하게 제어할 수 있습니다.

이러한 시스템 호출 함수들은 프로세스 관리, 파일 시스템 조작, 프로세스 간 통신 등 다양한 시스템 프로그래밍 작업에 필수적으로 사용됩니다.


perror와 strerror는 C 언어에서 오류 처리와 관련된 중요한 함수들입니다. 두 함수 모두 <string.h> 헤더 파일에 정의되어 있습니다.

## perror 함수

perror 함수는 시스템 오류 메시지를 표준 오류 스트림(stderr)에 출력합니다.

### 구문
```c
void perror(const char *str);
```

### 주요 특징

1. errno 변수에 저장된 현재 오류 코드에 해당하는 오류 메시지를 출력합니다[1].

2. 사용자가 지정한 문자열(str)을 오류 메시지 앞에 추가할 수 있습니다[3].

3. 출력 형식: "[사용자 지정 문자열]: [시스템 오류 메시지]"[7].

4. 반환값이 없습니다(void 함수)[7].

### 사용 예시
```c
FILE *fp = fopen("nonexistent.txt", "r");
if (fp == NULL) {
    perror("File opening error");
}
```

출력 예: "File opening error: No such file or directory"

## strerror 함수

strerror 함수는 오류 번호에 해당하는 오류 메시지 문자열의 포인터를 반환합니다.

### 구문
```c
char *strerror(int errnum);
```

### 주요 특징

1. 주어진 오류 번호(errnum)에 해당하는 오류 메시지 문자열을 반환합니다[4].

2. 반환된 문자열은 수정하면 안 되며, 후속 strerror 호출에 의해 덮어쓰일 수 있습니다[6].

3. errno.h에 정의된 오류 코드를 사용합니다[2].

4. 스레드 안전성을 위해 strerror_r 함수를 대신 사용할 수 있습니다[6].

### 사용 예시
```c
#include <stdio.h>
#include <string.h>
#include <errno.h>

int main() {
    FILE *fp = fopen("nonexistent.txt", "r");
    if (fp == NULL) {
        printf("Error: %s\n", strerror(errno));
    }
    return 0;
}
```

출력 예: "Error: No such file or directory"

## perror와 strerror의 차이점

1. 출력 방식: perror는 직접 stderr에 출력하지만, strerror는 문자열 포인터를 반환합니다[1][4].

2. 사용자 정의 메시지: perror는 사용자 정의 메시지를 추가할 수 있지만, strerror는 오류 메시지만 반환합니다[3][4].

3. 유연성: strerror는 반환된 문자열을 프로그램에서 다양하게 활용할 수 있어 더 유연합니다[6].

4. 오류 번호 지정: perror는 현재 errno 값을 사용하지만, strerror는 특정 오류 번호를 지정할 수 있습니다[1][4].

두 함수 모두 오류 처리에 유용하며, 상황에 따라 적절한 함수를 선택하여 사용할 수 있습니다.

errno는 시스템 오류 번호를 저장하는 전역 변수로, <errno.h> 헤더 파일에 정의되어 있습니다

C 언어의 예약어(키워드)는 언어 자체에 내장된 특별한 의미를 가진 단어들로, 변수명이나 함수명 등의 식별자로 사용할 수 없습니다. 대표적인 예약어로는 auto, break, case, char, const 등이 있습니다.

반면 errno는 라이브러리 함수에서 오류 발생 시 오류 코드를 저장하는 용도로 사용되는 변수입니다. 프로그래머가 직접 errno의 값을 변경할 수도 있으며, 라이브러리 함수의 오류를 확인하는 데 사용됩니다.

따라서 errno는 C 언어의 예약어가 아니라 표준 라이브러리에서 정의된 특수한 용도의 변수입니다.