[TCP/IP] 리눅스 저수준 파일 입출력과 파일 디스크립터

2021. 9. 5. 16:39·Backend/Network

# 표준 입출력과 표준 에러에 할당된 파일 디스크립터

파일 디스크립터 대상
0 표준입력 : Standard Input
1 표준출력 : Standard Output
2 표준에러 : Standard Error

파일과 소켓은 생성의 과정을 거쳐야 파일 디스크립터가 할당됨.

위의 세가지 입출력 대상은 별도의 생성과정없이도 프로그램이 실행되면 자동으로 할당되는 파일 디스크립터.


# 파일열기

- 데이터를 읽거나 쓰기 위해 파일을 열 때 사용하는 함수

- 첫 번째 인자 : 대상이 되는 파일의 이름 및 경로 정보

- 두 번째 인자 : 파일의 오픈 모드 정보(파일의 특성 정보)를 전달

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

int open(const char *path, int flag);
-> 성공시 파일 디스크립터, 실패시 -1반환

- path : 파일 이름을 나타내는 문자열의 주소 값 전달

- flag : 파일의 오픈 모드 정보 전달

 

위 함수의 두 번째 매개변수 flag에 전달할 수 있는 값과 그 의미는 밑 표 참고

하나 이상의 정보를 비트 OR 연산자로 묶어서 전달 가능 

오픈 모드 의미
O_CREAT 필요하면 파일을  생성
O_TRUNC 기존 데이터 전부 삭제
O_APPEND 기존 데이터 보존하고, 뒤에 이어서 저장
O_RDONLY 읽기 전용으로 파일 오픈
O_WRONLY 쓰기 전용으로 파일 오픈
O_RDWR 읽기, 쓰기 겸용으로 파일 오픈

# 파일 닫기

- 밑 함수 호출하면서 파일 디스크립터를 인자로 전달하면 해당 파일은 종료됨

- 파일 뿐만 아니라 소켓도 해당 -> 파일과 소켓을 구분하지 않는다. (리눅스 운영체제의 특징)

#include <unistd.h>

int close(int fd);
-> 성공 시 0, 실패 시 -1 반환

- fd : 닫고자 하는 파일 또는 소켓의 파일 디스크립터 전달


# 파일에 데이터 쓰기

- 파일에 데이터를 출력(전송)하는 함수

#include <unistd.h>

ssize_t write(int fd, const void *buf, size_t nbytes);
-> 성공 시 전달한 바이트 수, 실패 시 -1 반환

- fd : 데이터 전송 대상을 나타내는 파일 디스크립터 전달

- buf : 전송할 데이터가 저장된 버퍼의 주소 값 전달

- nbytes : 전송할 데이터의 바이트 수 전달


# 파일의 생성 및 데이터의 저장

low_open.c

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

void error_handling(char* message);

int main(void)
{
	int fd;
	char buf[]="Let's go!\n";
	
	fd=open("data.txt", O_CREAT|O_WRONLY|O_TRUNC);
	if(fd==-1)
		error_handling("open() error!");
	printf("file descriptor: %d \n", fd);

	if(write(fd, buf, sizeof(buf))==-1)
		error_handling("write() error!");

	close(fd);
	return 0;
}

void error_handling(char* message)
{
	fputs(message, stderr);
	fputc('\n', stderr);
	exit(1);
}

/*
root@com:/home/swyoon/tcpip# gcc low_open.c -o lopen
root@com:/home/swyoon/tcpip# ./lopen
file descriptor: 3 
root@com:/home/swyoon/tcpip# cat data.txt
Let's go!
root@com:/home/swyoon/tcpip# 
*/

12행 : 파일 오픈 모드가 O_CREAT, O_WRONLY, O_TRUNC의 조합으로 아무것도 저장되어 있지 않은 새로운 파일이 생성되어 쓰기만 가능

이미 data.txt라는 이름의 파일이 존재한다면, 이 파일의 모든 데이터는 지워져 버림.

17행 : fd에 저장된 파일 디스크립터에 해당되는 파일에 buf에 저장된 데이터를 전송하고 있음

리눅스의 cat명령을 통해 data.txt 파일에 저장된 내용을 출력,

출력내용은 파일에 데이터가 제대로 전송되었음을 보여줌


# 파일에 저장된 데이터 읽기

- write함수의 상대적인 기능을 제공하는 read함수는 데이터를 입력(수신)하는 기능의 함수

#include <unistd.h>
ssize_t read(int fd, void #buf, size_t nbytes);
-> 성공 시 수신한 바이트 수(단 파일의 끝을 만나면 0), 실패 시 -1반환

- fd : 데이터 수신대상을 나타내는 파일 디스크립터 전달

- buf : 수신한 데이터를 저장할 버퍼의 주소값 전달

- nbytes : 수신할 최대 바이트 수 전달

 

- 위에서 생성한 data.txt에 저장된 데이터를 read함수를 이용해 읽어오는 예제

low_read.c

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

#define BUF_SIZE 100

void error_handling(char* message);

int main(void)
{
	int fd;
	char buf[BUF_SIZE];
	
	fd=open("data.txt", O_RDONLY);
	if( fd==-1)
		error_handling("open() error!");
	
	printf("file descriptor: %d \n" , fd);
	
	if(read(fd, buf, sizeof(buf))==-1)
		error_handling("read() error!");

	printf("file data: %s", buf);
	
	close(fd);
	return 0;
}

void error_handling(char* message)
{
	fputs(message, stderr);
	fputc('\n', stderr);
	exit(1);
}

/*
root@com:/home/swyoon/tcpip# gcc low_read.c -o lread
root@com:/home/swyoon/tcpip# ./lread
file descriptor: 3 
file data: Let's go!
root@com:/home/swyoon/tcpip# 
*/

13행 : data.txt 읽기전용으로 open

18행 : read함수로 11행에 선언된 배열 buf에 읽어들인 데이터 저장


# 파일 디스크립터와 소켓

- 파일, 소켓 생성후 반환되는 파일 디스크립터의 값을 정수형태로 비교하는 예제

fd_seri.c

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>

int main(void)
{	
	int fd1, fd2, fd3;
	fd1=socket(PF_INET, SOCK_STREAM, 0);
	fd2=open("test.dat", O_CREAT|O_WRONLY|O_TRUNC);
	fd3=socket(PF_INET, SOCK_DGRAM, 0);
	
	printf("file descriptor 1: %d\n", fd1);
	printf("file descriptor 2: %d\n", fd2);
	printf("file descriptor 3: %d\n", fd3);
	
	close(fd1);
	close(fd2);
	close(fd3);
	return 0;
}

9~11행 : 1 파일, 2 소켓 생성

13~15행 : 앞서 생성한 파일 디스크립터의 정수 값 출력

 

'Backend > Network' 카테고리의 다른 글

[TCP/IP] Iterative 에코서버, 에코 클라이언트  (0) 2021.09.18
[TCP/IP] TCP와 UDP  (0) 2021.09.18
[TCP/IP] 리눅스 환경에서 C언어로 Hello World 서버/클라이언트 구현하기  (0) 2021.09.05
[TCP_IP] VMware 설치방법  (0) 2021.08.30
'Backend/Network' 카테고리의 다른 글
  • [TCP/IP] Iterative 에코서버, 에코 클라이언트
  • [TCP/IP] TCP와 UDP
  • [TCP/IP] 리눅스 환경에서 C언어로 Hello World 서버/클라이언트 구현하기
  • [TCP_IP] VMware 설치방법
min_sol
min_sol
  • min_sol
    비글개발연구소🐾
    min_sol
  • 전체
    오늘
    어제
    • 분류 전체보기 (279)
      • Programming (128)
        • Algorithm (52)
        • JAVA (40)
        • GIS (5)
        • PyQt (10)
        • C# (11)
        • Mobile (6)
        • AI (4)
      • Backend (36)
        • Spring (14)
        • JSP (11)
        • Network (5)
      • Frontend (29)
        • React (11)
        • Vue (13)
        • Next.js (4)
      • Database (10)
        • PostgreSQL (1)
        • Oracle (8)
        • Elasticsearch (1)
      • DevOps (8)
        • Linux (7)
        • Mac (1)
      • Tools (32)
        • IntelliJ (1)
        • VSCode (1)
        • GitHub (10)
        • RPA (20)
      • Security (9)
      • etc (21)
        • ERROR (5)
        • 세미나 | 교육 (10)
        • 자격증 (1)
        • 일상 (2)
        • 2021 (2)
  • 인기 글

  • 태그

    spring
    자료구조
    PyQt
    자바
    RPA
    명품자바에센셜
    연습문제
    PyQt5
    생능출판
    VUE
    Java
    자동화
    이클립스
    스윙
    백준
    계산기
    vue.js
    알고리즘
    jsp
    코딩테스트
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
min_sol
[TCP/IP] 리눅스 저수준 파일 입출력과 파일 디스크립터
상단으로

티스토리툴바