42Seoul의 Minishell 과제에서 허용되는 External functions를 정리한 포스트이다.
GNU readline 은 CLI에서 줄 편집 및 입력 기록 저장 등의 역할을 하는 라이브러리이다.
GNU 프로젝트에 속해 있으며 입력 자동 완성, 커서 이동, 잘라내기, 복사, 붙여넣기 등의 기능을 지원하며, Bash 등의 CLI 기분 인터랙티브 소프트웨어에서 사용된다.
-lreadline
컴파일러 플래그를 사용해 컴파일해야한다.
#include <stdio.h>
#include <readline/readline.h>
char *readline (const char *prompt);
prompt
를 출력하고 프롬프트를 열어 표준 입력으로 문자열을 입력받으며, 개행(newline, /n)을 받으면 지금까지 입력된 문자열을 리턴한다.
문자열을 입력받기 전까지는 다음 코드로 진행되지 않는다.
rl_replace_line()
, rl_redisplay()
등으로 프롬프트가 비워져도 계속 문자열을 받는 상태가 된다.
반환값
#include <stdio.h>
#include <readline/readline.h>
int rl_on_new_line(void);
일반적으로 개행을 출력한 후 새(빈) 줄로 이동했음을 업데이트 함수에 알리는 함수이다.
rl_redisplay()
를 실행하기 위해 필요한 함수이다.
반환값
#include <stdio.h>
#include <readline/readline.h>
void rl_replace_line (const char *text, int clear_undo);
rl_line_buffer
의 내용을 text
로 바꾼다.
즉, 현재까지 입력된 프롬프트의 문자열을 text
로 바꾸어주는 함수이다.
가능한 경우 포인트와 마크가 유지된다.
clear_undo
는 내부적으로 유지중인 undo_list를 초기화할 지의 여부를 결정한다.
clear_undo
가 0이 아니면 현재 행과 관련된 실행 취소 목록이 지워진다.
ctrl + C
처럼 프롬프트를 입력하지는 않고 새로운 프롬프트를 출력해야 할 때 rl_replace_line(””, 1);
처리를 해준다면 새로운 프롬프트를 비워줄 수 있게 된다.
char *rl_line_buffer
지금까지 모은 라인이다.rl_extend_line_buffer
함수는rl_line_buffer
에 할당된 메모리를 늘리는 데 사용할 수 있다.
#include <stdio.h>
#include <readline/readline.h>
void rl_redisplay (void)
rl_line_buffer
의 현재 내용을 반영하도록 화면에 표시되는 내용을 변경한다.
rl_replace_line()
을 하지 않으면 작동하지 않으며, readline()
함수의 인자로 넣은 문자열을 다시 출력한다.
char *rl_line_buffer
지금까지 모은 라인이다.rl_extend_line_buffer
함수는rl_line_buffer
에 할당된 메모리를 늘리는 데 사용할 수 있다.
#include <stdio.h>
#include <readline/history.h>
void add_history (const char *string)
history 목록의 끝에 문자열을 배치한다. 연결된 데이터 필드(있는 경우)는 NULL로 설정된다.
즉, 인자에 넣은 문자열을 history에 저장하며, 프롬프트가 열린 상태에서 키보드 방향키 위, 아래를 통해 이제껏 프롬프트에 입력한 문자열을 불러올 수 있다.
스택(stack)처럼 가장 마지막에 넣은 문자열부터 불러온다.
#include <readline/readline.h>
#include <readline/history.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *str;
while (1)
{
// 무한루프로 readline 함수 호출, 라인을 계속해서 입력받는다.
str = readline("prompt : ");
if (!str)
break ;
printf("str = %s\n", str);
// history에 문자열을 저장
add_history(str);
// 할당된 메모리 해제
free(str);
}
return (0);
}
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <stdlib.h>
int main(void)
{
char *str;
while (1)
{
str = readline("prompt : ");
if (!str)
break ;
rl_on_new_line();
rl_replace_line("replace line\n", 1);
rl_redisplay();
printf("\n");
add_history(str);
free(str);
}
system("leaks a.out; rm -rf a.out");
return (0);
}
#include <stdio.h>
int printf(const char *format, ...);
여러 종류의 데이터를 다양한 서식에 맞춰 출력하는 함수
반환값
#include <stdlib.h>
void * malloc(size_t size);
원하는 만큼 동적으로 메모리를 할당하여 주소값을 반환하는 함수이며, 동적으로 메모리를 할당할때 Heap(힙)영역에 할당 한다.
반환값
#include <stdlib.h>
void free(void *ptr);
동적으로 할당된 메모리를 해제한다.
반환값
#include <fcntl.h>
int open(const char *path, int oflag, ...);
파일을 사용하기 위해 여는(open) 함수
반환값
파일을 open()
할 때 용도에 따라 oflag에 옵션을 지정하여 연다.
아래의 옵션은 모두 <fcntl.h>
에 정의되어 있다.
열기 옵션 | 설명 |
---|---|
O_RDONLY | 읽기 전용으로 열기 |
O_WRONLY | 쓰기 전용으로 열기 |
O_RDWR | 읽기와 쓰기 모두 가능 |
추가적인 옵션도 존재한다.
기타 옵션 | 설명 |
---|---|
O_CREAT | 해당 파일이 없으면 생성한다. (주의) O_CREATE 가 아니라 끝에 E가 없는 O_CREAT 다. O_CREAT로 파일을 생성하게 된다면 파일의 접근권한을 지정하기 위해 접근 권한 값을 추가해야 한다. ex: open( "badayak.txt", O_WRONLY \| OCREAT, 0644); |
O_EXCL | O_CREAT를 사용했을 때, 파일이 이미 있어도 열기가 가능하여 쓰기를 하면 이전 내용이 사라진다. O_CREAT를 사용할 때, O_EXCL를 함께 사용하면, 이미 파일이 있을 때에는 open() 되지 않아 이전 파일을 보존할 수 있다.ex: fd = open( "./test.txt", O_WRONLY \| O_CREAT \| O_EXCL, 0644) 즉, 이렇게 O_EXCL을 함께 사용하면, 파일이 없을 경우에는 O_CREAT 영향을 받아 쓰기 전용의 파일이 생성하고, 파일이 이미 존재하면 open() 이 실패된다. |
O_TRUNC | 기존의 파일 내용을 모두 삭제한다. |
O_APPEND | 파일을 추가하여 쓰기가 되도록 open 후에 쓰기 포인터가 파일의 끝에 위치하게 된다. |
O_NOCITTY | 열기 대상이 터미널일 경우, 이 터미널이 프로그램의 제어 터미널로 할당하지 않는다. |
O_NONBLOCK | 읽을 내용이 없을 때에는 읽을 내용이 있을 때까지 기다리지 않고 바로 복귀한다. |
O_SYNC | 쓰기를 할 때, 실제 쓰기가 완료될 때 까지 기다린다. 즉, 물리적으로 쓰기가 완료되어야 복귀하게 된다. |
이 외에도 더 다양한 옵션들이 존재한다.
#include <unistd.h>
ssize_t read(int fildes, const void *buf, size_t, nbyte);
파일에 데이터를 읽는 함수
반환값
#include <unistd.h>
ssize_t write(int fildes, const void *buf, size_t nbyte);
파일에 데이터를 출력하는 함수
반환값
#include <unistd.h>
int close(int fildes);
열린 파일을 닫는 함수
close()를 호출하면 fd 를 해제하며, 파일에서 프로세스를 분리한다.
프로세스가 종료되면 커널이 프로세스의 열린 파일들을 모두 자동으로 닫기 때문에 명시적으로 close() 함수를 호출하지 않는 프로그램들도 많다.
반환값
#include <unistd.h>
pid_t fork(void);
현재 실행되는 프로세스에 대한 복사본을 만들어 자식 프로세스를 생성하는 함수이다.
반환값
#include <sys/wait.h>
pid_t wait(int *stat_loc);
현재 프로세스가 fork()
한 자식 프로세스(child proccess)의 상태 변화를 monitoring한다. 주로 자식 프로세스가 종료되었을 때에 많이 사용하고, child process의 종료 원인이 무엇인지를 확인한다.
만약 부모 프로세스에서 SIGCHLD
시그널에 대해서 signal()
또는 sigaction()
으로 SIG_IGN
으로 설정하지 않았다면, wait()
/ waitpid()
등의 함수로 자식 프로세스 종료를 기다려야한다. 그렇지 않으면, 종료된 자식 프로세스는 메모리에서 사라지지않고 좀비("zombie" 또는 "defunct")상태가 된다.
좀비 상태에서는 kill
등으로 절대로 종료시킬 수 없으며, 오로지 부모 프로세스가 종료해야만 사라지게 된다. 따라서 SIGCHLD
signal에 대해서 SIG_IGN
으로 설정하거나 signal handler 함수에 wait()
/ waitpid()
함수로 자식 프로세스 상태를 읽어주어야 종료된다. 또는 주기적으로 waitpid()
를 호출하여 wait상태인 자식 프로세스의 memory를 free 시켜주어야 한다.
좀비 프로세스(zombie process)
자식 프로세스가 정상 또는 비정상적으로 종료했는 데, 부모 프로세스에게 종료상태(정상종료면 main함수의 return값 또는 exit함수의 파라미터값, 비정상종료이면 signal 번호)를 전달하기 위해서 최소한의 resource로 유지하고 있는 프로세스를 말한다.
즉, 자식 프로세스가 완전히 사라지면 부모 프로세스에게 실행 결과를 전달을 할 수 없으니, 아무런 기능도 하지 않고 오로지 부모 프로세스에게 종료 메시지를 전달하기 위해서 떠 있 는 프로세스이다.
만약, 부모 프로세스가 종료가 되면 좀비 프로세스의 부모 프로세스가 init 프로세스인 1번으로 바뀌고 init 프로세스가 wait 또는SIGCHLD
에 대해SIG_IGN
으로 처리해버리기 때문에 좀비 프로세스는 사라진다.
반환값
stat_loc
관련 매크로(macro)들
macros | description |
---|---|
WIFEXITED(statloc) | child process가 정상 종료 시 true 반환 |
WEXITSTATUS(statloc) | WIFEXITED 가 true 를 반환한 경우에만 사용 가능, 하위 8비트를 참조하여 child process가 exit , _exit , _Exit 에 넘겨준 인자 값을 받음 |
WIFSIGNALED(statloc) | signal에 의해 종료된 경우 true를 반환 |
WTERMSIG(statloc) | child process를 종료시킨 signal의 숫자를 반환하며 WIFSIGNALED 가 true 를 반환했을 경우 사용 |
ECHILD | 호출자의 child process가 없는 경우를 나타냄 |
EINTR | 시스템 콜이 인터럽트 되었을 때 사용 |
#include <sys/wait.h>
pid_t wait3(int *statloc, int options, struct rusage *rusage);
자식 프로세스가 종료되는 것을 기다리며, 종료된 프로세스의 상태와 자원 사용량을 알려주는 함수.
pid_t wait4(pid_t pid, int *statloc, int options, struct rusage *rusage);
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *stat_loc, int options);
매개변수로 주어진 pid 번호의 자식 프로세스가 종료되거나, 시그널(signal) 함수를 호출하는 신호가 전달될 때까지 waitpid()
함수를 호출한 영역에서 일시 중지된다.
stat_loc
의 하위 8비트에는 0이 저장되며, 상위 8비트에는 프로세스가 종료되게 한 exit함수의 인자가 기록된다.stat_loc
의 하위 8비트에는 프로세스를 종료시킨 시그널 번호가 저장되며, 상위 8비트에는 0이 저장된다.waitpid()
옵션 정보WCONTINUED
: 중단 되었다가 재개된 자식 프로세스의 상태를 받는다.WNOHANG
: 자식 프로세스가 종료되었는지 실행 중인지 확인하고 바로 복귀한다. 즉, 부모 프로세스는 block되지 않은다.WUNTRACED
: 중단된 자식 프로세스의 상태를 받는다.pid 값에 따라 다음과 같이 처리된다.
|pid|의미|
|양수|프로세스 ID가 pid인 자식 프로세스를 기다림|
|0|프로세스 그룹 ID가 호출한 프로세스의 ID와 같은 자식 프로세스를 기다린다.|
|-1|임의의 자식 프로세스를 기다림|
|-1 이외의 음수|프로세스 그룹 ID가 pid의 절대값과 같은 자식 프로세스를 기다림|
반환값
WNOHANG
을 사용하였고, 자식 프로세스가 종료되지 않았다면 0을 리턴stat_loc
관련 매크로(macro)들
macros | description |
---|---|
WIFEXITED(statloc) | child process가 정상 종료 시 true 반환 |
WEXITSTATUS(statloc) | WIFEXITED 가 true 를 반환한 경우에만 사용 가능, 하위 8비트를 참조하여 child process가 exit , _exit , _Exit 에 넘겨준 인자 값을 받음 |
WIFSIGNALED(statloc) | signal에 의해 종료된 경우 true를 반환 |
WTERMSIG(statloc) | child process를 종료시킨 signal의 숫자를 반환하며 WIFSIGNALED 가 true 를 반환했을 경우 사용 |
ECHILD | 호출자의 child process가 없는 경우를 나타냄 |
EINTR | 시스템 콜이 인터럽트 되었을 때 사용 |
options
관련 매크로들(marcos)
macros | description |
---|---|
WCONTINUED | 중단되었다가 재개된 child process의 상태를 받는다 |
WNOHANG | 기다리는 pid가 종료되지 않아 즉시 종료 상태를 회수할 수 없는 경우 호출자는 반환값으로 0을 받으며, 종료되지 않음 |
WUNTRACED | 중단된 자식 프로세스의 상태를 받는다 |
#include <signal.h>
void (*signal(int sig, void (*func)(int)))(int);
시그널(signal)을 받아 해당 함수를 실행시키는 함수
반환값
SIG_ERR
리턴시그널은 <signal.h>
헤더 파일에 정의되어있고, 시그널에 따른 기본 처리는 프로세스를 종료하거나, 코어 덤프를 생성한다.
No | Name | Default Action | Description |
---|---|---|---|
1 | SIGHUP | terminate process | terminal line hangup |
2 | SIGINT | terminate process | interrupt program |
3 | SIGQUIT | create core image | quit program |
4 | SIGILL | create core image | illegal instruction |
5 | SIGTRAP | create core image | trace trap |
6 | SIGABRT | create core image | abort program (formerly SIGIOT) |
7 | SIGEMT | create core image | emulate instruction executed |
8 | SIGFPE | create core image | floating-point exception |
9 | SIGKILL | terminate process | kill program |
10 | SIGBUS | create core image | bus error |
11 | SIGSEGV | create core image | segmentation violation |
12 | SIGSYS | create core image | non-existent system call invoked |
13 | SIGPIPE | terminate process | write on a pipe with no reader |
14 | SIGALRM | terminate process | real-time timer expired |
15 | SIGTERM | terminate process | software termination signal |
16 | SIGURG | discard signal | urgent condition present on socket |
17 | SIGSTOP | stop process | stop (cannot be caught or ignored) |
18 | SIGTSTP | stop process | stop signal generated from keyboard |
19 | SIGCONT | discard signal | continue after stop |
20 | SIGCHLD | discard signal | child status has changed |
21 | SIGTTIN | stop process | background read attempted from control terminal |
22 | SIGTTOU | stop process | background write attempted to control terminal |
23 | SIGIO | discard signal | I/O is possible on a descriptor (see fcntl(2)) |
24 | SIGXCPU | terminate process | cpu time limit exceeded (see setrlimit(2)) |
25 | SIGXFSZ | terminate process | file size limit exceeded (see setrlimit(2)) |
26 | SIGVTALRM | terminate process | virtual time alarm (see setitimer(2)) |
27 | SIGPROF | terminate process | profiling timer alarm (see setitimer(2)) |
28 | SIGWINCH | discard signal | Window size change |
29 | SIGINFO | discard signal | status request from keyboard |
30 | SIGUSR1 | terminate process | User defined signal 1 |
31 | SIGUSR2 | terminate process | User defined signal 2 |
#include <signal.h>
int kill(pid_t pid, int sig);
kill()
함수는 쉘에서 프로세스를 죽이는 kill 명령과는 달리 프로세스에 시그널을 전송한다. 물론, 프로세스에 SIGKILL
을 보내면 쉘 명령의 kill과 같은 역할을 할 수도 있다.
특정 프로세스 뿐만 아니라 같은 그룹 ID가 같은 모든 프로세스에게 동시에 시그널을 전송할 수 있으며, 권한 안에 있는 모든 프로세스에게도 시그널을 전송할 수 있다.
pid 값에 따라 다음과 같이 처리된다.
pid | 의미 |
---|---|
양수 | 지정한 프로세스 ID에만 시그널을 전송 |
0 | 함수를 호출하는 프로세스와 같은 그룹에 있는 모든 프로세스에 시그널을 전송 |
-1 | 함수를 호출하는 프로세스가 전송할 수 있는 권한을 가진 모든 프로세스에 시그널을 전송 |
-1 이외의 음수 | 첫 번째 인수 pid 의 절대값 프로세스 그룹에 속하는 모든 프로세스에 시그널을 전송 |
반환값
#include <stdlib.h>
void exit(int status);
status
는 운영체제에 전달하며 main함수의 return값과 같은 역할이다.status
값은 에러 코드와 같으므로 정상 종료시 0을, 에러로 인한 종료시 0이 아닌 숫자, 대체로 1을 반환한다.#include <unistd.h>
char *getcwd(char *buf, size_t size);
현재 작업 디렉토리의 full path 명을 문자열로 얻는다. 즉, 프로세스에서 디렉토리의 위치를 알아내는 함수이다.
malloc()
을 통해 메모리를 할당한 후 작업 디렉토리 경로를 문자열로 반환한다.반환값
#include <unistd.h>
int chdir(const char *path);
현재 작업 디렉토리를 변경하는 함수이다.
반환값
#include <sys/stat.h>
int stat(const char *restrict path, struct stat *restrict buf);
파일의 크기, 권한, 생성일시, 최종 변경일 등 파일의 상태나 파일의 정보를 얻는 함수이다.
symbolic link인 파일을 path로 넘기면 그 원본 파일의 정보를 얻는다.
symbolic link
링크를 연결하여 원본 파일을 직접 사용하는 것과 같은 효과를 내는 링크이다.
윈도우의 바로가기와 비슷한 개념
반환값
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <time.h>
int main(int argc, char *argv[])
{
struct stat sb;
if (argc != 2) {
fprintf(stderr, "Usage: %s <pathname>\n", argv[0]);
return 1;
}
if (stat(argv[1], &sb) == -1) {
perror("stat");
return 1;
}
printf("File type: ");
switch (sb.st_mode & S_IFMT) {
case S_IFBLK: printf("block device\n"); break;
case S_IFCHR: printf("character device\n"); break;
case S_IFDIR: printf("directory\n"); break;
case S_IFIFO: printf("FIFO/pipe\n"); break;
case S_IFLNK: printf("symlink\n"); break;
case S_IFREG: printf("regular file\n"); break;
case S_IFSOCK: printf("socket\n"); break;
default: printf("unknown?\n"); break;
}
printf("I-node number: %ld\n", (long) sb.st_ino);
printf("Mode: %lo (octal)\n", (unsigned long) sb.st_mode);
printf("Link count: %ld\n", (long) sb.st_nlink);
printf("Ownership: UID=%ld GID=%ld\n", (long) sb.st_uid, (long) sb.st_gid);
printf("Preferred I/O block size: %ld bytes\n", (long) sb.st_blksize);
printf("File size: %lld bytes\n", (long long) sb.st_size);
printf("Blocks allocated: %lld\n", (long long) sb.st_blocks);
printf("Last status change: %s", ctime(&sb.st_ctime));
printf("Last file access: %s", ctime(&sb.st_atime));
printf("Last file modification: %s", ctime(&sb.st_mtime));
return 0;
}
>> File type: regular file
>> I-node number: 4579628
>> Mode: 100644 (octal)
>> Link count: 1
>> Ownership: UID=103967 GID=4222
>> Preferred I/O block size: 4096 bytes
>> File size: 2660 bytes
>> Blocks allocated: 8
>> Last status change: Tue Oct 4 16:52:32 2022
>> Last file access: Tue Oct 4 16:52:38 2022
>> Last file modification: Tue Oct 4 16:52:32 2022
#include <sys/stat.h>
int lstat(const char *restrict path, struct stat *restrict buf);
파일의 크기, 권한, 생성일시, 최종 변경일 등 파일의 상태나 파일의 정보를 얻는 함수이다.
symbolic link인 파일을 path로 넘기면 symbolic link 파일 자신의 정보를 얻는다.
symbolic link
링크를 연결하여 원본 파일을 직접 사용하는 것과 같은 효과를 내는 링크이다.
윈도우의 바로가기와 비슷한 개념
반환값
#include <sys/stat.h>
int fstat(int fildes, struct stat *buf);
열려진 파일의 크기, 권한, 생성일시, 최종 변경일 등 열려진 파일의 상태나 파일 정보를 얻는 함수이다.
open()
등으로 생성한 file descriptor반환값
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* 파일의 종류 및 접근권한 */
nlink_t st_nlink; /* hardlink 된 횟수 */
uid_t st_uid; /* 파일의 owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* 파일의 크기(bytes) */
blksize_t st_blksize; /* blocksize for file system I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
이 중 주요 내용을 보면
st_mode
는 파일의 종류와 파일에 대한 access 권한 정보를 담고 있다.
아래 POSIX macro를 통해 파일의 종류를 확인할 수 있다.
S_ISREG(buf.st_mode) : 일반 파일 여부
S_ISDIR(buf.st_mode) : 디렉토리 여부
S_ISCHR(buf.st_mode) : character device 여부
S_ISBLK(buf.st_mode) : block device 여부
S_ISFIFO(buf.st_mode) : FIFO 여부
S_ISLNK(buf.st_mode) : symbolic link 여부
S_ISSOCK(buf.st_mode) : socket 여부 (주로 AF_UNIX로 socket 생성된 경우)
또한 st_mode
는 파일 유형값으로 직접 비트연산 &
로 확인할 수 있다.
S_IFMT 0170000 type of file
/* 파일 유형 */
S_IFSOCK 0140000 socket
S_IFLNK 0120000 symbolic link
S_IFREG 0100000 regular file
S_IFBLK 0060000 block device
S_IFDIR 0040000 directory
S_IFCHR 0020000 character device
S_IFIFO 0010000 named pipe (FIFO)
/* 특수 권한 설정 bit */
S_ISUID 0004000 set-user-ID bit
S_ISGID 0002000 set-group-ID bit
S_ISVTX 0001000 sticky bit
접근 권한 값(chmod의 값과 같음)
S_IRWXU 00700 mask for file owner permissions
S_IRUSR 00400 owner has read permission
S_IWUSR 00200 owner has write permission
S_IXUSR 00100 owner has execute permission
S_IRWXG 00070 mask for group permissions
S_IRGRP 00040 group has read permission
S_IWGRP 00020 group has write permission
S_IXGRP 00010 group has execute permission
S_IRWXO 00007 mask for permissions for others (not in group)
S_IROTH 00004 others have read permission
S_IWOTH 00002 others have write permission
S_IXOTH 00001 others have execute permission
st_atime
, st_mtime
, st_ctime member
변수는 time관련 함수(<time.h>
내 localtime()
, ctime()
등)를 이용하여 conversion후에 사용하면 쉽게 사용할 수 있다.
#include <unistd.h>
int unlink(const char *path);
파일을 삭제하는 system call 함수이다. 정확하게는 unlink()
는 hard link의 이름을 삭제하고 hard link가 참조하는 count를 1 감소시킨다.
hard link의 참조 count가 0이 되면, 실제 파일의 내용이 저장되어 있는 disk space를 free하여 OS가 다른 파일을 위해서 사용할 수 있도록 한다.
따라서 hard link를 생성하지 않은 파일은 바로 disk space를 해제하여 사실상 파일 삭제한다.
그러나 open()
으로 파일이 열려진 상태에서 unlink()
를 호출하여 hard link 참조 count가 0이 되어도 directory entry에서 파일 이름 등의 정보는 삭제되지만 disk space는 해제되지 않는다.
하드 링크(hard link)
파일 시스템의 파일의 이름과 연결되는 디렉터리 엔트리이다.
모든 디렉터리 기반의 파일 시스템들은 각 파일의 원래 이름을 제공하는 (적어도) 하나의 하드 링크가 있어야 한다.
"하드 링크"라는 용어는 동일한 파일에 대해 일반적으로 하나 이상의 하드 링크를 허용하는 파일 시스템에만 사용된다.
반환값
#include <unistd.h>
int execve(const char *path, char *const argv[], char *const envp[]);
실행가능한 파일인 filename의 실행코드를 현재 프로세스에 적재하여 기존의 실행코드와 교체하여 새로운 기능으로 실행하는 system call 함수이다.
즉, 현재 실행되는 프로그램의 기능은 없어지고 filename 프로그램을 메모리에 loading하여 처음부터 실행한다.
main(int argc, char *argv[])
에서 argv와 비슷하며, main함수에는 argc가 있지만 execve에는 argc가 없으므로 main의 argv과 달리 array 끝에 NULL이 있다.반환값
- signal 설정이 default로 변경
- mmap()으로 생성 memory mapping이 보존되지 않는다.
- shared memory 영역에 대한 access가 해제
- message queue descriptor가 close
- named semaphore가 close
- timer가 보존되지 않는다.
- opendir로 open된 directory stream이 close
- memory lock이 보존되지 않는다.
- atexit(), on_exit()로 등록된 exit handler가 해제
- 모든 thread가 사라진다.
- aio_read()/aio_write()과 같은 async I/O 동작이 취소
- 일반 file descriptor는 close되지 않는다.
#include <unistd.h>
int dup(int fd);
file descriptor를 받아 복제하여 반환한다.
반환값
#include <unistd.h>
int dup2(int fd, int fd2);
fd2
에 fd
가 가리키는 file descriptor를 복제하고 해당 file desctiptor를 반환한다.
반환값
#include <unistd.h>
int pipe(int fd[2]);
서로 독립된 프로세스들이 데이터를 주고받을 수 있도록 하는 pipe file descriptor를 설정한다.
fd[0]
는 read, fd[1]
은 write을 의미한다.
파이프 자체는 fork()
를 하더라도 복사되지 않으며, 방향성이 없다.
반환값
#include <dirent.h>
DIR *opendir(const char *filename);
특정 directory의 하위에 있는 파일명 및 디렉토리명 등의 목록을 얻기 위한 DIR *
(디렉토리 스트림)를 생성하는 함수이다.
반환값
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
디렉토리의 하위에 있는 파일 및 디렉토리 정보를 1개 읽는다. 즉, 1회 호출에 1건의 정보를 return 한다.
읽는 순서는 시간 순서, 파일명 순서, 파일 크기 등 어떤 기준이 없으므로 기본적으로 sorting이 되어 있지 않다.
opendir()
또는 fdopendir()
을 통해 생성된 DIR *
반환값
struct dirent {
ino_t d_ino; /* inode number */
off_t d_off; /* offset to the next dirent */
unsigned short d_reclen; /* length of this record */
unsigned char d_type; /* type of file; not supported by all file system types */
char d_name[256]; /* filename */
};
#include <dirent.h>
int closedir(DIR *dirp);
opendir()
으로 open한 DIR *
에 대해, 더 이상 directory의 파일목록을 검색을 하지 않을 경우에 closedir()
로 DIR *
를 close하는 함수이다.
opendir()
또는 fdopendir()
을 통해 생성된 DIR *
반환값
#include <string.h>
char *strerror(int errnum);
오류 메세지 문자열을 가리키는 포인터를 얻어오는 함수이다. 즉, errnum
의 값을 통해 발생하였던 오류에 알맞은 오류 메세지를 가리키는 포인터를 리턴한다.
strerror()
에 의해 출력되는 오류 메세지는 현재 사용중인 컴파일러나 플랫폼에 따라 다를 수 있다.
반환값
#include <sys/errno.h>
extern int errno
system call 함수 또는 일부 함수들에서 오류 발생 시 해당 오류를 나타내는 오류번호가 담기는 전역 변수이다.
각 운영체제 마다 errno
에 담기는 번호와 오류 메세지가 다양하다.
#include <unistd.h>
int isatty(int fd);
file descriptor가 터미널에 연결되어 있는지 확인하는 함수이다.
반환값
#include <unistd.h>
char *ttyname(int fd);
file descriptor에 대한 터미널 이름을 얻어오는 함수이다.
일반적으로 ttyname은 자신의 터미널이름을 가져오는데 사용되므로 프로세스가 만들어질 때 기본적으로 생성되는 파일지정자(0, 1, 2)에 대해서 적용하는 경우가 많다.
반환값
#include <unistd.h>
int ttyslot(void);
터미널에 대한 DB의 entry index를 반환한다.
반환값
#include <sys/ioctl.h>
int ioctl(int fildes, unsigned long request, ...);
device driver
와 통신하기 위한 함수이다.
즉, 장치에게 요청을 보낼 때 사용되는 시스템 콜(system call) 함수이다.
What is
device driver
?
하드웨어 주변 장치는 커널 안에 직접적으로 주소 지정을 할 수 있다.
응용 프로그램이 장치와 통신하길 원할 수 있다. (하드웨어 장치의 기능을 사용하고 싶을 때)
그런데 커널 개발자는 어떤 장치가 커널 안에 주소를 할당받을지, 그 장치에는 어떤 기능이 있는지 알 수가 없다.
따라서 확장가능한 모듈식으로 커널을 유연하게 설계할 필요가 있었고, 그렇게 해서 나온게 device driver이다.
즉, 어떠한 장치가 연결될 지 모르는 상황에서 device driver라는 하나의 중간 계층을 둠으로써 문제를 해결할 수 있다.
open()
을 통해 얻는 fildes가 된다. (O_NONBLOCK
flag 이용 권장)사용자 정의하에 이용되는 경우에는 ioctl 함수의 반환값을 이용할 수도 있다.
일반적으로 함수 호출 시 마지막 인자에는 char *
타입을 이용한다.
반환값
#include <stdlib.h>
char *getenv(const char *name);
name
에 해당하는 환경변수의 값에 대한 문자열을 반환한다.
반환값
name
에 해당하는 환경변수 값#include <termios.h>
int tcsetattr(int fildes, int optional_actions, const struct termios *termios_p);
터미널 파일에 대한 속성을 설정하는 함수
TCSNOW
→ 속성을 바로 변경TCSADRAIN
→ 송신을 완료한 후 변경TCSAFLUSH
→ 송수신 완료 후 변경반환값
#include <termios.h>
int tcgetattr(int fildes, struct termios *termios_p);
터미널 파일에 대한 속성을 얻어서 termios_p에 저장하는 함수
반환값
#include <termios.h>
struct termios
{
tcflag_t c_iflag; /* input flags */
tcflag_t c_oflag; /* output flags */
tcflag_t c_cflag; /* control flags */
tcflag_t c_lflag; /* local flags */
cc_t c_cc[NCCS]; /* control chars */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
};
termios구조체는 터미널의 거의 모든 속성을 다룰 수 있는 변수들로 이루어져있다.
#include <termios.h>
int tgetent(char *bp, const char *name);
TermCap
의 쿼리를 수행할 수 있도록 만드는 루틴이다.
일반적으로 name
에 할당하는 값은 TERM 환경변수로 할당된 터미널 타입을 이용한다.
What is
TermCap
?
Termcap은 Unix 계열 컴퓨터에서 사용되는 소프트웨어 라이브러리 및 데이터베이스이다.
반환값
#include <termios.h>
int tgetflag(char *id);
쿼리로 사용할 이름을 인자로 받는다. 플래그를 얻을 수 있는 쿼리의 경우 1, 그렇지 않은 경우 0을 반환한다.
#include <termios.h>
int tgetnum(char *id);
쿼리로 사용할 이름을 인자로 받는다.
함수 수행에 성공하면 그 값을 반환하고 그렇지 않으면 -1을 반환한다.
#include <termios.h>
char *tgetstr(char *id, char **area);
쿼리로 사용할 이름을 인자로 받는다.
쿼리에 해당하는 Escape Sequence
를 얻을 수 있다면 그 값을 반환하고 그렇지 않은 경우 NULL을 반환한다.
#include <termios.h>
char *tgoto(const char *cap, int col, int row);
매개변수를 지정된 기능으로 인스턴스화한다. 출력은 tputs
로 전달된다.
col
과 row
를 고려한 Cursor Motion
의 Escape Sequence
를 반환한다. 함수 수행에 실패하면 NULL을 반환한다.
#include <termios.h>
int tputs(const char *str, int affcnt, int (*putc)(int));
Escape Sequence
에 대한 터미널 출력 결과를 내는 루틴이다.
tgetstr
또는 tgoto
를 통해 얻은 값을 str
인자로 받는다.
affcnt
의 경우 영향을 끼칠 줄의 수를 나타나는데, 1로 주는 것이 일반적.
putc
는 ASCII 문자 값을 인자로 받아 표준 출력의 쓰기 작업으로 터미널에 ASCII 문자 값을 출력해주는 함수.