[Linux]Directory

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

🔊 Directory

  • File은 directory entry를 포함한다.
  • directory와 file의 차이점
    • 디렉토리는 creat와 open 이용이 불가하다.
    • errno = EISDIR : dir에 O_WRONLY, O_RDWR bit를 설정하면 오류가난다.
    • write를 이용한 변경이 불가하다.
    • kernel에서만 dir write가 가능하다.
  • Directory entry : i-node - character field
	link("abc", "xyz");
  • abc와 xyz는 같은 i-node를 갖는다.
  • unlink system call을 이용하여 link를 제거할 수 있다.


🔊 Directory permission

  • regular file permission과 같은 방식이다.
  • 하지만 file과는 의미가 다르다.
    • read permission : file과 subdirectory의 리스트
    • write permission : 새로운 파일을 생성하거나 기존 파일을 삭제
    • execute permission(search bit) : chdir()사용시 필요한 권한
  • 만약 /usr/include/stdio.h를 열어보려면
    • /, /usr/ /usr/include의 execute 권한이 필요하다.
  • S_ISVTX : Sticky bit
    • 이 비트가 설정되면 제거와 이름 재정의는 write permission이 있는 유저나 file이나 directory의 소유자, superuser만 가능하다.



🔊 디렉토리 조작하기

dirent 구조체

  • directory entry : i-node - directory name(null-terminated)
  • i-node가 0일 경우는 directory의 빈곳을 의미한다.
    #include <dirent.h>

    struct dirent {
            ino_t d_ino;                /* i-node number */
            char  d_name[NAME_MAX + 1]; /* null-terminated filename */
          }

🔈 mkdir( )

    #include <sys/stat.h>

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

    /*  성공시 0, 실패시 -1이 반환된다. */
  • 권한은 umask를 통한 변경이 가능하다.
  • .과 .. directory를 자동으로 생성한다.
  • directory 속 file에 접근하기 위해서는 execute bit가 설정되어있어야한다.
	$ mkdir dir
    $ cat > dir/file.txt
    test test test ^D
    
    $ chmod 666 dir //execute 권한 해제
    $ ls dir //read 권한 필요
    dir/file.txt
    $ cat dir/file/txt
    cat : dir/file.txt: 허가 거부됨 //execute 권한 없어서
    
    $ chmod 111 dir //execute 권한만 설정
    $ ls dir : 허가거부됨 //read 권한 없어서
    $ cat dir/file.txt //execute 권한만있으면 file 접근가능
    test test test 

🔈 rmdir( )

  • 빈 directory를 삭제한다.
    #include <unistd.h>

	int rmdir(const char *pathname);

    /*  성공시 0, 실패시 -1이 반환된다. */

🔈opendir( ) & closedir( )

    #include <dirent.h>

	DIR *opendir(const char *dirname);

    /*  성공시 pointer, 실패시 NULL이 반환된다. */
    
    
    int closedir(DIR *dirptr);
    
     /*  성공시 0, 실패시 -1이 반환된다. */
  • NULL을 이용하여 error checking은 필수이다.
    #include <stdlib.h>
    #include <dirent.h>

    main(){
       DIR *dp;
       if ((dp = opendir("/tmp/dir1")) == NULL){
          fprintf (stderr, "Error on opening directory /tmp/dir1\n");
          exit(1);
       }

       /* 디렉토리에 대한 코드를 처리한다. */
       closedir(dp);
    }

🔈readdir( )

  • 첫 readdir 호출하면 첫 directory entry가 반환된다.
  • 다음부터는 pointer를 이용하여 다음 entry로 이동한다.
    #include <dirent.h>

    struct dirent *readdir(DIR *dp);

    /* 성공시 poiter, dirtory의 끝이거나 실패시 NULL 반환 */

🔈rewinddir( )

    #include <dirent.h>

    void rewinddir(DIR *dp);
    
     /*  성공시 0, 실패시 -1이 반환된다. */
  • dp의 첫번째 entry로 이동한다.
    #include <dirent.h>

    int my_double_ls (const char *name){
       struct dirent *d;
       DIR *dp;

       /* 디렉토리를 열어보고, 실패여부를 점검함 */
       if ((dp=opendir(name)) == NULL)
       return (-1);

       /* 
       		readdir(dp) - EOF 만나면 -1 반환
       */
       while (d = readdir(dp)){
          if (d->d_ino !=0)
             printf ("%s\n", d->d_name);
       }

       rewinddir(dp); /* 디렉토리의 시작으로 되돌아간다. */
		
       /* i-node를 다시 출력한다. */
       while (d = readdir(dp)){
          if (d->d_ino != 0)
             printf ("%s\n", d->d_name);
       }
      closedir (dp);
    }



🔊 Current working directory

  • 각 프로세스는 cwd를 갖는다.
  • shell에서 process를 실행할 때 그 directory가 cwd가 된다.

🔈chdir( )

    #include <unistd.h>

    int chdir(const char *path);

     /*  성공시 0, 실패시 -1이 반환된다. */
  • error
    • path가 유효한 directory가 아닐 경우
    • 해당 디렉토리에 해당되는 directory들 중에 execute permission이 없을 경우
fd1 = open(/usr/ben/abc”, O_RDONLY);
fd2 = open(/usr/ben/xyz”, O_RDWR);

chdir(/usr/ben”); //파일 생성시 간편하게 할 수 있다.
fd1 = open(“abc”, O_RDONLY);
fd2 = open(“xyz”, O_RDWR);

🔈getcwd( )

  • 현재 디렉토리의 포인터가 반환된다.
    #include <unistd.h>

    char *getcwd(char *name, size_t size);

     /*  성공시 name, 실패시 NULL이 반환된다. */
  • 현재 디렉토리 이름이 name을 가르키는 포인터의 이름으로 복사된다.
  • name 문제
    • errno : ERANGE
  • 작업 디텍토리를 프린트한다.
    #include <stdio.h>
    #include <unistd.h>
    #define VERYBIG 200

    void my_pwd (void);

    main()
    {
       my_pwd();
    }

    void my_pwd (void)
    {
       char dirname[VERYBIG];

       if ( getcwd(dirname, VERYBIG) == NULL)
        perror("getcwd error");
       else
        printf("%s\n", dirname);
    }



🔊 UNIX file systmems

sync and fsync

  • memory에서 disk로 변환될 때, 바로 disk로 옮기는 것이 아니라 OS data space에서 캐시로 저장한다.
  • read는 cache로 buffer에 저장되는 것이다.
  • sync : flush, disk, main memory about file system을 이용
  • fsync : data가 아닌 flush호출과 특정 파일 관련된 특성

🔈 sync( ) & fsync( )

     #include <unistd.h>

     int fsync(int filedes);

     void sync(void);

     /*  성공시 0, 실패시 -1이 반환된다. */
  • fsync는 disk에 file data를 다 옮길때까지 반환되지 않는다.
  • sync는 다 옮겨지지 않아도 반환된다. 코드 실행마다 같이 실행된다.



🔊 Divice file

  • device들은 부여된 번호로 접근이 가능하다.
  • major number & minor number로 구성되어있다.
    • major number : device의 타입
    • minor number : 특정 device의 인스턴스
  • 유저는 device number을 이용하여 접근하지 않는다.
  • device file
    • device file의 i-node는 device number을 포함한다. (i-node -> i_rdev)
    • 주변 device의 인터페이스를 제공한다.
    • file system에 포함된다.
    • superuser를 통해서만 생성이 가능하다.
	mknod(path, mode, dev);

- disk, teminals, printer와 같은 주변 디바이스 filenames를 통하여 접근이 가능하며 그에대한 정보는 /dev에 들어있다. - command에서 device file은 일반 file과 같이 사용된다.
    $ cat fred > /dev/lp
    $ cat fred > /dev/rmt0

    #include<fcntl.h>

    main()
    {
       int i, fd;

       fd = open("/dev/tty00", O_WRONLY);

       for(i = 0; i< 100; i++)
          write(fd, "x", 1);

       close(fd);
    }

Block and character device files

  • Block device file : bdevsw[]
    • disk, magnetic tape 등등
  • Character device file : cdevse[]
    • terminal, modem, printer 등등
  • 이 두 테이블은 major device number(i-node에 저장된)를 index로하여 사용한다.
  • transmitting data
    • device fils의 i-node는 read, write로 접근가능하다.
    • major(inode->i_rdev)로 block인지 character인지 알기위하여 i-node의 flag를 확인한다.

	struct stat {
    		mode_t st_mode;
            dev_t st_rdev; //device number

🏷️ stat 구조체

  • st_mode

  • type : 앞의 4bit

macrofile type
S_ISREG()regular file
S_ISDIR()directory file
S_ISCHR()character special file
S_ISBLK()block special file
S_ISFIFO()pipe or fifo
S_ISLNK()sysbolic link
S_ISSOCK()socket
    if(S_ISCHR(buf.st_mode))
       printf(“It’s character device\n”);
    else
       printf(“It’s not\n”);

    switch(stat->st_mode & S_IFMT){
      case S_IFBLK:
      case S_IFCHR:
      case S_IFIFO:
      case S_IFREG:
      case S_IFDIR:
      case S_IFLNK:
      case S_IFSOCK:
    }
  • st_rdev
    • character/block만 갖는 값이다.
    int main(int argc, char *argv[]) { 
       int i; 
       struct stat buf; 
       stat(argv[1], &buf);

       printf("dev = %d/%d", major(buf.st_dev), minor(buf.st_dev)); 

       if (S_ISCHR(buf.st_mode) || S_ISBLK(buf.st_mode)) { 
          printf(" (%s) rdev = %d/%d",(S_ISCHR(buf.st_mode))?"character":"block" 
                                     , major(buf.st_rdev)
                                     , minor(buf.st_rdev)); 
       } 
       printf("\n"); 
       exit(0); 
    } 

0개의 댓글

관련 채용 정보