[Linux]The File

공부기록·2023년 10월 19일
0
post-thumbnail

File and FileSystem

  • file
    • byte 단위의 연속된 data를 저장한다.
    • 각 byte들은 disk에 존재할 수 있다.
    • 외부디바이스에 동일한 interface를 갖고있다.
  • filesystem
    • 파일과 데이터를 저장하거나 관리한다.
    • 파일의 탐색과 접근이 용이하다.
    • 하드디스크나 CD-ROM과 같은 저장소를 이용하여 데이터를 저장한다.


리눅스 명령어

이름설명
open파일을 설정값을 부여하여 열 수 있다.
create빈 파일을 생성한다.
close열려있던 파일을 닫는다.
read파일 읽는다.
write파일에 내용을 입력한다.
lseekfile의 특정 byte로 이동한다.
unlink파일을 제거한다.
remove파일을 제거한다.
fcntl파일을 제어한다.

File Descriptor

  • 모든 파일은 fd값을 갖는다.
  • read나 write의 인자로 쓰인다.
  • 0 ~ 2 는 고정되어있다.
file descriptor의미
0표준 입력
1표준 출력
2표준 에러

open( )

  • 보통 O_CREAT와 함께 쓰여 생성하면서 열린다.
#include <fcntl.h> 

int open(const char *pathname, int flags, [mode_t mode]);

/*성공시 fd, 실패시 -1을 반환한다.*/
  • flag
    • O_RDONLY, O_WRONLY, O_RDWR
    • O_APPEND, O_CREAT,
    • O_EXCL : O_CREAT와 같이 쓰일때 파일이 존재하면 ERROR를 출력한다
    • O_TRUNC : 파일이 존재하면 해당파일을 초기화시킨다.
  • mode : O_CREAT와 함께 쓰이는 인자로 허용 권한을 의미한다.

creat( )

  #include <fcntl.h> 

  int creat(const char *pathname, mode_t mode);

  /*성공시 fd, 실패시 -1을 반환한다.*/
  • 파일이 이미 존재하면 두번째인자는 무시되고 truncate 된다.
  • creat는 읽기전용으로 열린다.
  fd1 = creat(/tmp/newfile”, 0644);
  fd2 = open(/tmp/newfile”, O_WRONLY|O_CREAT|O_TRUNC, 0644);
  //fd1 = fd2

File Permission

  • file의 권한 설정
  • file type - user - group - others 순
  • -rwxrwxrwx

  • 권한 변경
	$ chmod g+w 파일명
    $ chmod 764 파일명

mode_t

  • usr : user, grp : group, oth : other
  • r : read, w : write, x : execution, rwx : 셋 다
이름설명
S_IRUSR유저 읽기 허용
S_IWUSR유저 쓰기 허용
S_IXUSR유저 실행 허용
S_IRWXU유저 읽기, 쓰기, 실행 허용
S_IRGRP그룹 읽기 허용
S_IROTH외부 읽기 허용
S_ISUIDset user ID on execution
S_ISGIDset group ID on execution
	int fd;
    mode_t fdmode = { S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH );
    fd = open("file", O_RDWR | O_CREAT, fdmode);

new file의 owner와 권한

  • file을 생성할 때에는 parent 디렉토리에 write permission 허용되어야한다. 새로운 file을 link해야되기 때문이다.
  • euid와 guid는 현 process의 것으로 설정된다.

close( )

  #include <unistd.h>

  int close(int filedes);

  /*성공시 0, 실패시 -1 반환*/

read( )

  • 지정된 byte수만큼 복사한 다음 현재 file position에서 다음에 읽을 곳으로 file position을 다시 지정한다.
	#include <unistd.h>

	ssize_t read(int fd, void *buf, size_t bytes);

	/*성공시 읽어드린 byte수, EOF을 만나면 0, 실패시 -1을 반환*/

write( )

  • memory에서 지정된 byte만큼 file에 작성한 다음 file position을 다음으로 다시 지정한다.
  • 원래 있던 파일에 write하면 기존데이터가 새로운 데이터로 덮어쓰기된다.
  • O_APPEND를 이용하여 offset을 끝으로 지정하면 기존 파일을 이어쓸 수 있다.
  #include <unistd.h>

  ssize_t write(int fd, const void *buf, size_t byte);

  /*성공시 쓰여진 byte수, 실패시 -1 반환*/

file copy 예제

	int copyfile(const char *name1, const char *name2){
    	int infile, outfile;
        ssize_t nread;
        char buf[BUFSIZE]; /*BUFSIZE 512*/
        
        if((infile = open(name1, O_RDONLY)) == --1)
        	return -1;
        if((outfile = open(name2, FMODE, PERM) == -1){
        	close(infile);
            return -2;
        }
        
        /*buf에 infile의 내용을 적고 그 값을 outfile에 적어넣음*/
        while(nread = read(infile, buf, BUFSIZE) > 0){
        	if(write(outfile, buf, nread) < nread){
            	close(infile);
                close(outfile);
                return -3;
            {
        }
        
        close(infile)
        close(outfile)
        
        if(nread == -1) return -4;
        else return 0;
   }
   
   int main(){
   		infile("test.in", "test.out");
   }
  • read,write의 BUFSIZE는 증가할수록 성능이 향상한다. BUFSIZE가 증가하면 시스템콜이 줄어 모드가 SWITCHING하는 비용을 줄일 수 있기도하다.
  • write의 시스템콜이 빠른 이유 : 진짜 쓰는게 아니라 data를 buffer로 변환시킨 것이라서

lseek( )

  #include <unistd.h>

  off_t lseek(int fd, off_t offset, int start_flag);

  /*성공 new fiel offset, 실패시 -1 반환*/
  • file offset : read나 write가 어디서 일어날지를 나타내는 표시이다.
  • start_flag
    • SEEK_SET : 파일의 첫 position
    • SEEK_CUR : 현재 position
    • SEEK_END : 파일의 끝 position
	fd = open(fname, O_RDWR);
    lseek(fd, (off_t)0, SEEK_END); /* file position을 끝으로 설정*/
    write(fd, outbuf, OBSIZE);
    
    ==
    
    fd = open(fname, O_WRONLY | O_APPEND);
    write(fd, outbuf, OBSIZE);
    
    /*filesize 반환*/
    off_t filesize;
    filesize = lseek(fd, (off_t)0, SEEK_END);



File Share

process table

  • process state
  • process ID
  • uid, guid
  • program file
  • file descriptor table
  • memory mapping
  • saved registers
  • stack pointer

process table entry

  • fd flags
  • file pointer

file table

  • file status flags(read, write)
  • current file offset
  • v-node pointer

v-node structure

  • v-node information
  • i-node information
  • current file size

  • 같은 file이라도 open때마다 새로운 fd값 생성.
  • 각갹의 file table이 생성된다.

dup( ) & dup2( )

	#include <unistd.h>

	int dup(int filedes);
	int dup2(int filedes, int filedes2);

	/*성공시 새 파일의 fd값, 실패시 -1 반환*/
  • process table entry에서 다른 fd값이 가진 두 process가 같은 file table을 가르키게된다.
  • 두 table은 같은 v-node table을 가르킨다.
	#include <unistd.h>
    
    fd3 = dup(1);
    fd4 = open("test", O_RDONLY); //fd4 = 4
    
    dup2(3, fd4);
    

  • fd3과 fd4는 같은 file table을 가르키게되고 count는 2가된다.

## fcntl( ) - 이미 실행되어있는 파일의 속성을 변경시킨다.
	#include <fcntl.h>

	int fcntl(int filedes, int cmd, ...);

	/*성공시 cmd에 따른 값이, 실패시 -1이 반환된다.*/    
  • cmd
    • F_DUPFD : 존재하는 fd값을 복제한다.
    • F_GETFD or F_STEFD : get/set file descriptor flags
    • F_GETFL or F_GETFL : get/set file status flags
	#include <fcntl.h>

    int filestatus(int filedes)
    {
      int arg1;
		
      /*fd에 해당하는 file의 status 값을 가져와 저장한다.*/
      if (( arg1 = fcntl (filedes, F_GETFL)) == -1)
      {
        printf ("filestatus failed\n"); 
        return (-1);
      }

      printf ("File descriptor %d: ",filedes);

      /*
      	access mode bit를 이용하여 접근 권한을 확인할 수 있다.
      */
      switch ( arg1 & O_ACCMODE){
        case O_WRONLY: printf ("write-only"); break;
        case O_RDWR:   printf ("read-write"); break;
        case O_RDONLY: printf ("read-only");  break;
        default: printf("No such mode");
      }
		
      /* 특정 flag가 설정되어있는지 확인하는 법 */
      if (arg1 & O_APPEND)
        printf (" -append flag set");

      printf ("\n");
      return (0);
    }

Redirection

  1. fd 0에는 표준입력이 연결되어있음. file table이 /dev/fd/0's v-node를 가르키게 된다.
	$ prog_name
    $ prog_name < infile
	dup2(infile, 0);
  • fd 0의 filetable의 v-node ptr은 infile's v-node를 가르키게된다.

  1. fd 1은 표준출력을 담당한다. file table이 dev/fd/1's v-node를 가르키게 된다.
	prog_name > outfile
	dup2(outfile, 1);
  • fd 1의 file table의 v-node ptr은 outfile's v-node를 가르키게된다.

  • 입력을 표준 입력으로 받고 출력을 표준 출력으로 내보낸다.

	#incldue <stdlib.h>
    #include <unistd.h>
    
    #define SIZE 512
    
    main(){
    	ssize_t nread;
        char buf[SIZE];
        
        while((nread = read(0, buf, SIZE)) > 0)
        	write(1, buf, nread);
        exit(0);
    }
        
	$ io
    This is line 1 (enter)
    This is line 1
    <Ctrl-D>
    $
  • read는 terminal로 입력받고 다음 라인에 다시 출력한다.



표준 I/O Library

  • UNIX I/O (system call)

    • 데이터를 byte의 연속으로 처리한다.
  • Standard I/O

    • Buffering 자동화
    • 프로그래머 친화적 인터페이스
    • 이용에 용이한 라이브러리 제공
  • Standard는 File* 이용하고 UNIX는 file desciptor를 이용하여 file에 접근한다.

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

    main()
    {
        FILE *stream;

        if ( ( stream = fopen ("junk", "r")) == NULL)
        {
           printf ("Could not open file junk\n");
           exit (1);
        }
	}
  • Standard I/O Library
    • fopen and fclose
    • reading and writing bytes : fread and fwrite
    • reading and wrtiing text lines : fgets and fputs
    • fscanf and fprintf

fopen( )

	#include <stdio.h>
    
    FILE *fopen(const char *restrict pathname, const char *restrict type);
    
    /* 성공시 file pointer, 실패시 error */
  • type
    • r or rb : open for reading
    • w or wb : truncate to 0 length or create for writing
    • a or ab : append
    • r+ or r+b or rb+ : open for reading and writing
    • w+ or w+b or wb+ : truncate to 0 length or for reading and writing
    • a+ or a+b or ab+ : open or create for reading and writing at end of file

getc( ) , putc( )

	#include <stdio.h>
    
    int getc(FILE *istream);
    /* 성공시 다음 character를, EOF on end of file */
    
    
    int putc(int c, FILE *ostream);
    /* 성공시 c, 실패시 EOF */
	int c;
    FILE *istream, *ostream;
    
    while((c=getc(istream)) != EOF)
    	putc(c, ostream);

Buffering

  • 사용중인 buffer는 처음 실행시 malloc을 호출한다.

fprintf( )

  • writing error message
	#include <stdio.h>
    
    int fprintf(FILE *restrict fp, const char *restrict format, ...);
    
    /* 성공시 output된 char의 갯수를, 실패시 음수를 반환한다. */
	#include <stdio.h>
    #include <stdlib.h>

    int notfound(const char *progname, const char *filename)
    {
        fprintf (stderr, "%s: file %s not found\n", progname, filename);
        exit (1);
    }



Error Handling

  • system call 발생시
    • 성공시는 0을 반환하고, error 발생시 -1을 반환한다.
    • errno에 설정된 error code가 설정된다.
    • error code는 E로 시작한다.
	#include <string.h>
    #include <stdio.h>
    
    char *strerror(int errnum);
    void perror(count char *msg);
  • 에러사항 출력
	#include <stdio.h>
    #include <fcntl.h>
    #include <errno.h>
    
    void main(int argc, char** argv){
    	int fd;
        if((fd = open("nonesuch", O_RDONLY)) == -1)
        	fprintf(stderr, "ENOENT: %s\n", stderror(errno));
        
        errno = EACESS; //permission denied.
        
        /* errono의 값과 연관된 메세지가 출력된 다음 줄바꾸기 문자가 이어진다. */
        perror(argv[0]);
    ENOENT: No such files or directory
    a.out: Permission denied

	#include <stdio.h>
    #include <fcntl.h>
    #include <errno.h>
    
    main() {
    	int fd;
        
        fd = open(“nonesuch”, O_RDONLY); //errno = ENOENT
    	fprintf(stderr, "error %d\n", errno); 
    	perror(“first position”);
        
    	fd = open(“existfile”, O_RDONLY); //errno = EACESS
    	fprintf(stderr, "error %d\n", errno); 
    	perror(“second Position”);
	} 
    error 2
    First position : There is no such files
    error 3
    Second position : There is no access permission

0개의 댓글

관련 채용 정보