시스템 호출은 프로그램이 직접 액세스할 수 없는 서비스를 제공하기 위해 시스템 커널에 수행하는 호출입니다. 예를 들어, 모니터 및 키보드와 같은 입력 및 출력 장치에 대한 액세스를 제공합니다. 생성, 열기, 읽기, 쓰기 등의 입출력 시스템 호출을 위해 C 프로그래밍 언어에서 제공하는 다양한 기능을 사용할 수 있습니다.
I/O 시스템 호출로 넘어가기 전에 몇 가지 중요한 용어에 대해 알아야 합니다.
중요한 용어
파일 설명자란 무엇입니까?
파일 설명자는 프로세스의 열린 파일을 고유하게 식별하는 정수입니다.
파일 설명자 테이블: 파일 설명자 테이블은 요소가 파일 테이블 항목에 대한 포인터인 파일 설명자인 정수 배열 인덱스의 모음입니다. 각 프로세스마다 운영 체제에 하나의 고유한 파일 설명자 테이블이 제공됩니다.
파일 테이블 항목: 파일 테이블 항목은 열린 파일에 대한 메모리 내 대체 구조로, 파일 열기 요청을 처리할 때 생성되며 이러한 항목은 파일 위치를 유지합니다.
표준 파일 설명자 : 프로세스가 시작되면 해당 프로세스 파일 설명자 테이블의 fd(파일 설명자) 0, 1, 2가 자동으로 열립니다. (기본적으로) 이러한 3개의 fd는 각각 다음과 같은 파일에 대한 파일 테이블 항목을 참조합니다. /dev/tty
/dev/tty : 터미널의 메모리 내 대체물입니다.
단말기 : 키보드/비디오 화면이 결합된 화면입니다.
stdin에서 읽기 => fd 0에서 읽기 : 키보드에서 문자를 쓸 때마다 stdin에서 fd 0까지 읽고 /dev/tty라는 파일에 저장합니다.
stdout에 쓰기 => fd 1에 쓰기 : 비디오 화면에 대한 출력을 볼 때마다 /dev/tty라는 파일에서 나온 것이며 fd 1을 통해 화면의 stdout에 기록됩니다.
stderr에 쓰기 => fd 2에 쓰기 : 비디오 화면에 오류가 표시됩니다. 이는 fd 2를 통해 화면의 stderr에 기록된 파일에서도 발생합니다.
입출력 시스템 호출
기본적으로 I/O 시스템 호출에는 총 5가지 유형이 있습니다.
1. C 생성
create() 함수는 C에서 새로운 빈 파일을 생성하는 데 사용됩니다. create() 함수를 사용하여 생성하려는 파일의 권한과 이름을 지정할 수 있습니다. 내부에 정의되어 있습니다. 헤더 파일과 인수로 전달되는 플래그는 내부에 정의됩니다. 헤더 파일.
C의 create() 구문
int create (char * filename , mode_t mode );>
매개변수
- 파일 이름: 생성하려는 파일 이름
- 방법: 새 파일의 권한을 나타냅니다.
반환 값
- 사용되지 않은 첫 번째 파일 설명자를 반환합니다(0, 1, 2 fd가 예약되어 있으므로 프로세스에서 처음 사용을 생성할 때 일반적으로 3).
- 오류가 발생하면 -1을 반환합니다.
OS에서 C create()가 작동하는 방식
- 디스크에 새로운 빈 파일을 만듭니다.
- 파일 테이블 항목을 만듭니다.
- 사용되지 않은 첫 번째 파일 설명자가 파일 테이블 항목을 가리키도록 설정합니다.
- 사용된 파일 설명자를 반환합니다. 실패 시 -1입니다.
2. C 오픈
C의 open() 함수는 읽기, 쓰기 또는 두 가지 모두를 위해 파일을 여는 데 사용됩니다. 파일이 존재하지 않는 경우에도 생성이 가능합니다. 내부에 정의되어 있습니다. 헤더 파일과 인수로 전달되는 플래그는 내부에 정의됩니다. 헤더 파일.
C의 open() 구문
int open (const char* Path , int flags );>
매개변수
- 길: 열려고 하는 파일의 경로입니다.
- 사용 절대 경로 시작하는 / 당신이 있을 때 ~ 아니다 같은 디렉토리에서 작업 C 소스 파일로.
- 사용 상대 경로 확장자가 있는 파일 이름만 있으면 됩니다. 같은 디렉토리에서 작업 C 소스 파일로.
- 플래그: 파일을 여는 방법을 지정하는 데 사용됩니다. 다음 플래그를 사용할 수 있습니다.
플래그 | 설명 |
---|---|
O_RD만 | 읽기 전용 모드로 파일을 엽니다. |
O_WRONLY | 쓰기 전용 모드로 파일을 엽니다. |
O_RDWR | 읽기 및 쓰기 모드로 파일을 엽니다. |
O_CREATE | 파일이 없으면 만듭니다. |
O_EXCL | 이미 존재하는 경우 생성을 방지합니다. |
O_ 추가 | 파일을 열고 내용의 끝에 커서를 놓습니다. |
O_ASYNC | 신호에 의한 입력 및 출력 제어를 활성화합니다. |
O_CLOEXEC | 열린 파일에 대해 close-on-exec 모드를 활성화합니다. |
O_NONBLOCK | 열린 파일의 차단을 비활성화합니다. |
O_TMPFILE | 지정된 경로에 이름 없는 임시 파일을 만듭니다. |
OS에서 C open()이 작동하는 방식
- 디스크에서 기존 파일을 찾습니다.
- 파일 테이블 항목을 만듭니다.
- 사용되지 않은 첫 번째 파일 설명자가 파일 테이블 항목을 가리키도록 설정합니다.
- 사용된 파일 설명자를 반환합니다. 실패 시 -1입니다.
C open()의 예
씨
// C program to illustrate> // open system call> #include> #include> #include> #include> extern> int> errno> ;> int> main()> {> > // if file does not have in directory> > // then file foo.txt is created.> > int> fd = open(> 'foo.txt'> , O_RDONLY | O_CREAT);> > printf> (> 'fd = %d
'> , fd);> > if> (fd == -1) {> > // print which type of error have in a code> > printf> (> 'Error Number % d
'> ,> errno> );> > // print program detail 'Success or failure'> > perror> (> 'Program'> );> > }> > return> 0;> }> |
>
>
산출
fd = 3>
3. 닫기
C의 close() 함수는 파일 설명자가 끝났음을 운영 체제에 알리고 파일 설명자가 가리키는 파일을 닫습니다. 내부에 정의되어 있습니다. 헤더 파일.
C의 close() 구문
int close(int fd);>
매개변수
- fd: F 닫으려는 파일의 파일 설명자입니다.
반환 값
- 0 성공에.
- -1 오류가 발생했습니다.
OS에서 C close()가 작동하는 방식
- 파일 설명자 테이블의 요소 fd가 참조하는 파일 테이블 항목을 삭제합니다.
– 다른 프로세스가 이를 가리키지 않는 한! - 파일 설명자 테이블의 요소 fd를 다음으로 설정합니다. 없는
예제 1: C의 close()
씨
// C program to illustrate close system Call> #include> #include> #include> int> main()> {> > int> fd1 = open(> 'foo.txt'> , O_RDONLY);> > if> (fd1 <0) {> > perror> (> 'c1'> );> > exit> (1);> > }> > printf> (> 'opened the fd = % d
'> , fd1);> > // Using close system Call> > if> (close(fd1) <0) {> > perror> (> 'c1'> );> > exit> (1);> > }> > printf> (> 'closed the fd.
'> );> }> |
>
>
산출
opened the fd = 3 closed the fd.>
예 2:
씨
// C program to illustrate close system Call> #include> #include> int> main()> {> > // assume that foo.txt is already created> > int> fd1 = open(> 'foo.txt'> , O_RDONLY, 0);> > close(fd1);> > > // assume that baz.tzt is already created> > int> fd2 = open(> 'baz.txt'> , O_RDONLY, 0);> > > printf> (> 'fd2 = % d
'> , fd2);> > exit> (0);> }> |
>
>
산출
fd2 = 3>
여기, 이 코드에서는 먼저 open()이 반환됩니다. 삼 왜냐하면 메인 프로세스가 생성되면 fd 0, 1, 2 이미 에 의해 촬영되었습니다 표준입력 , 표준 출력, 그리고 표준 오류 . 따라서 사용되지 않은 첫 번째 파일 설명자는 다음과 같습니다. 삼 파일 설명자 테이블에서. 그 후 close() 시스템 호출은 무료입니다. 삼 파일 설명자를 설정한 다음 삼 파일 설명자 없는 . 따라서 두 번째 open()을 호출하면 사용되지 않은 첫 번째 fd도 삼 . 따라서 이 프로그램의 출력은 다음과 같습니다. 삼 .
4. C 읽기
파일 설명자 fd가 나타내는 파일에서 read() 함수는 지정된 양의 바이트를 읽습니다. cnt 로 표시된 메모리 영역에 대한 입력의 버프 . 성공적인 read()는 파일에 대한 액세스 시간을 업데이트합니다. read() 함수는 헤더 파일 내부에도 정의되어 있습니다.
C의 read() 구문
size_t read (int fd , void* buf , size_t cnt );>
매개변수
- fd: 데이터를 읽어올 파일의 파일 설명자입니다.
- 버프: 데이터를 읽을 버퍼
- CNT: 버퍼의 길이
반환 값
- 성공 시 읽은 바이트 수를 반환합니다.
- 파일 끝에 도달하면 0을 반환
- 오류 시 -1을 반환
- 신호 인터럽트 시 -1을 반환합니다.
중요사항
- 버프 오버플로로 인해 지정된 크기보다 작지 않은 길이의 유효한 메모리 위치를 가리켜야 합니다.
- fd 읽기 작업을 수행하려면 open()에서 반환된 유효한 파일 설명자여야 합니다. fd가 NULL이면 읽기에서 오류가 발생해야 하기 때문입니다.
- cnt 는 요청된 읽기 바이트 수이고, 반환 값은 실제 읽은 바이트 수입니다. 또한 읽기 시스템 호출이 cnt보다 적은 바이트를 읽어야 하는 경우도 있습니다.
C의 read() 예
씨
// C program to illustrate> // read system Call> #include> #include> #include> int> main()> {> > int> fd, sz;> > char> * c = (> char> *)> calloc> (100,> sizeof> (> char> ));> > fd = open(> 'foo.txt'> , O_RDONLY);> > if> (fd <0) {> > perror> (> 'r1'> );> > exit> (1);> > }> > sz = read(fd, c, 10);> > printf> (> 'called read(% d, c, 10). returned that'> > ' %d bytes were read.
'> ,> > fd, sz);> > c[sz] => ' '> ;> > printf> (> 'Those bytes are as follows: % s
'> , c);> > return> 0;> }> |
>
>
산출
called read(3, c, 10). returned that 10 bytes were read. Those bytes are as follows: 0 0 0 foo.>
foobar.txt가 6개의 ASCII 문자 foobar로 구성되어 있다고 가정합니다. 그러면 다음 프로그램의 출력은 무엇입니까?
씨
자바 형식 문자열
// C program to illustrate> // read system Call> #include> #include> #include> #include> int> main()> {> > char> c;> > int> fd1 = open(> 'sample.txt'> , O_RDONLY, 0);> > int> fd2 = open(> 'sample.txt'> , O_RDONLY, 0);> > read(fd1, &c, 1);> > read(fd2, &c, 1);> > printf> (> 'c = %c
'> , c);> > exit> (0);> }> |
>
>
산출
c = f>
설명자 fd1 그리고 fd2 각각은 자신의 열린 파일 테이블 항목을 갖고 있으므로 각 설명자는 해당 항목에 대한 자체 파일 위치를 갖습니다. foobar.txt . 따라서 다음에서 읽은 내용은 fd2 의 첫 번째 바이트를 읽습니다. foobar.txt 이고 출력은 다음과 같습니다. c = 에프 , 아니다 c = 오 .
5. C 쓰기
buf의 cnt 바이트를 fd와 연결된 파일이나 소켓에 씁니다. cnt는 INT_MAX(limits.h 헤더 파일에 정의됨)보다 커서는 안 됩니다. cnt가 0이면 write()는 다른 작업을 시도하지 않고 단순히 0을 반환합니다.
write()도 내부에 정의되어 있습니다. 헤더 파일.
C의 write() 구문
size_t write (int fd , void* buf , size_t cnt );>
매개변수
- fd: 파일 설명자
- 버프: 데이터를 쓸 버퍼입니다.
- CNT: 버퍼의 길이.
반환 값
- 성공 시 작성된 바이트 수를 반환합니다.
- 파일 끝에 도달하면 0을 반환합니다.
- 오류가 발생하면 -1을 반환합니다.
- 신호 인터럽트 시 -1을 반환합니다.
C 쓰기에 대한 중요 사항
- 쓰기 작업을 위해 파일을 열어야 합니다.
- 버프 buf 크기가 cnt보다 작으면 buf가 오버플로 조건으로 이어지기 때문에 최소한 cnt에 지정된 길이만큼 길어야 합니다.
- cnt 는 쓰기 위해 요청된 바이트 수이고, 반환 값은 쓰여진 실제 바이트 수입니다. 이런 경우가 발생합니다. fd cnt보다 쓸 바이트 수가 적습니다.
- write()가 신호에 의해 중단되면 효과는 다음 중 하나입니다.
- write()가 아직 데이터를 쓰지 않은 경우 -1을 반환하고 errno를 EINTR로 설정합니다.
- write()가 일부 데이터를 성공적으로 쓴 경우 중단되기 전에 쓴 바이트 수를 반환합니다.
C의 write() 예
씨
// C program to illustrate> // write system Call> #include> #include> main()> {> int> sz;> int> fd = open(> 'foo.txt'> , O_WRONLY | O_CREAT | O_TRUNC, 0644);> if> (fd <0)> {> > perror> (> 'r1'> );> > exit> (1);> }> sz = write(fd,> 'hello geeks
'> ,> strlen> (> 'hello geeks
'> ));> printf> (> 'called write(% d, 'hello geeks
', %d).'> > ' It returned %d
'> , fd,> strlen> (> 'hello geeks
'> ), sz);> close(fd);> }> |
>
>
산출
called write(3, 'hello geeks ', 12). it returned 11>
여기에서 코드를 실행한 후 foo.txt 파일을 보면 안녕하세요 괴짜들 . foo.txt 파일에 이미 일부 콘텐츠가 있는 경우 쓰기 시스템 호출이 콘텐츠를 덮어쓰고 모든 이전 콘텐츠는 삭제됨 그리고 오직 안녕하세요 괴짜들 내용은 파일에 있습니다.
예: printf 함수를 사용하지 않고 프로그램에서 hello world를 인쇄합니다.
씨
// C program to illustrate> // I/O system Calls> #include> #include> #include> #include> int> main(> void> )> {> > int> fd[2];> > char> buf1[12] => 'hello world'> ;> > char> buf2[12];> > // assume foobar.txt is already created> > fd[0] = open(> 'foobar.txt'> , O_RDWR);> > fd[1] = open(> 'foobar.txt'> , O_RDWR);> > write(fd[0], buf1,> strlen> (buf1));> > write(1, buf2, read(fd[1], buf2, 12));> > close(fd[0]);> > close(fd[1]);> > return> 0;> }> |
>
>
산출
hello world>
이 코드에서는 buf1 배열의 문자열 안녕 세계 먼저 stdin fd[0]에 기록된 다음 이 문자열이 buf2 배열의 stdin에 기록됩니다. 그런 다음 buf2 배열을 stdout에 쓰고 출력을 인쇄합니다. 안녕 세계 .