mount : 리눅스 터미널 파일시스템을 보는 방법

 

 

  • dev/sda1 on : 디스크가 실제로 mount되어 붙어있음
  • proc, sysfs on에 어플리케이션과 소통할 수 있는 통로(가상파일들) 시스템 정보를 얻어냄

cd /proc/ -> ls

  • 커널에서 사용자들에게 정보를 줌
  • 번호들이 쓰여있는 디렉토리들이 존재 : 프로세스의 정보들이 표시되어 있음
  • 이 정보들을 보고 운영체제, 프로세스의 상태를 볼 수 있음


top

  • cpu정보, 점유율

 


cat meminfo

  • 메모리의 정보들이 존재

 


cat cmdline

  • 커널 실행 옵션

 


cd /sys/ -> ls

  • 커널의 특정기능을 키거나 끌 때 sys에서 write하면 됨

  • 이렇게 리눅스나 유닉스에서는 모든 시스템 정보들이 파일을 통해서 이루어짐

프로그램을 만들기 앞서 사용될 시스템 콜들을 알아보겠습니다.

  • perror : print 에러 메시지 -> 에러 메시지들을 출력해주는 시스템 콜
  • exit(0) : 실행중이던 파일 종료

단순히 파일을 open하는 함수

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
int main(int argc,char *argv[]){
        int fd;
        if(argc != 2){
                printf("opentest filename\n");
                exit(0);
        }
        fd = open(argv[1],O_RDONLY);
        if(fd == -1){
                perror("open");
                exit(0);
        }
        else{
                printf("file %s open succes\n",argv[1]);
        }
        return 0;
}
cs
  1. argment를 받는 실행파일이기 때문에 main함수 안에 인자들을 넣음

  2. argment들이 2개가 아니라면 (-> ./실행파일 open할 파일이름) 잘못됨을 알리고 프로그램 종료

  3. 잘 입력 되었다면 fd에 read모드로 파일을 open하고

  4. fd가 -1(에러)이라면 에러메시지 출력 후 프로그램 종료

  5. 에러가 아니라면 파일이 열린것을 알림

 


유닉스의 cp명령어와 유사한 mycp프로그램을 작성

  • mycp는 첫 번째 인자로 지정된 파일을 두 번째 인자로 복사하는 함수

  • ex) ./mycp source-file dest-file

  • 따라서 source-file은 read only, dest-file은 read and write로 만들 것

  • read의 경우 몇 바이트씩 읽을지 정해야 함 -> buf의 크기는 size_t count

  • 정해진 만큼 읽다가 마지막 부분은 덜 읽어올 수 있음

  • write : 버퍼에 있는 내용을 카운트 만큼 씀

  • dest-file의 모드는 rw-rw-rw-로 세팅, 즉 (S_IRUSR,S_IWUSR,S_IRGRP,S_IWGRP,S_IROTH,S_IWOTH) -> 0666으로 표현 가능

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
 
#define SZ_BUF 1024
 
int main(int argc,char *argv[]){
        int fd_in;
        int fd_out;
 
        if(argc != 3){
                printf("mycp source_file dest_file\n");
        }
        fd_in = open(argv[1],O_RDONLY);
        fd_out = open(argv[2],O_RDWR|O_CREAT,0666);
 
        if(fd_in == -1 || fd_out == -1){
                perror("open");
                exit(0);
        }
        else{
                char *buffer[SZ_BUF];
                int nb;
 
                while(nb = read(fd_in, buffer, SZ_BUF)){
                        write(fd_out, buffer ,nb);
                }
                printf("success\n");
                close(fd_in);
                close(fd_out);
                exit(0);
        }
}
cs
  1. 버퍼사이즈를 1024로 define함

  2. fd_in과 fd_out을 선언

  3. argument가 3개일 경우만 실행

  4. fd_in은 첫 번째 파일, 즉 복사할 파일을 read only로 open

  5. fd_out은 두 번째 파일, 붙여넣을 파일을 read and write only로 open하고 파일이 존재하지 않을 경우 creat함/ 0666은 유저, 그룹, 다른사용자 까지 모두 읽고 쓸 수 있음을 의미

  6. fd_in 또는 fd_out이 오류가 나서 -1이 리턴됐다면 에러메시지를 출력하고 프로그램을 종료

  7. 제대로 return됐다면 buffer를 정해놓은 사이즈만큼 선언하고

  8. nb에 read가 안될때 까지 while문을 실행

  9. write로 fd_out에 읽어온만큼 작성

  10. 끝나면 fd_in과 fd_out을 close 후 프로그램 종료

 


write(2) 함수를 이용해 1byte씩 num-bytes만큼 반복하여 파일 끝에 붙여쓰기

  • 디폴트로는 open(2)시에 O_APPEND 플레그를 사용하여 파일 끝에 첨부 함

  • 3번째 인자로 x가 주어지는 경우, O_APPEND플레그를 사용하지 않고 각  byte를 첨부하기 위해서 lseek한 후에 write()를 사용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <stdio.h>
 
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
 
#include <unistd.h>
 
#include <errno.h>
 
#include <stdlib.h>
 
#include <string.h>
 
#define SZ_BUF 1024
 
int main (int argc, char *argv[])
{
   int fd;
   int num_bytes;
   if (argc == 3)
   {
      printf("use O_APPEND flag in open\n");
      num_bytes = atoi(argv[2]);
 
      fd = open(argv[1], O_WRONLY|O_CREAT|O_APPEND, 0666);
      if (fd == -1)
      {
         perror("cannot open!");
         exit(0);
      }
      int i;
      for(i = 0; i< num_bytes; i++)
      {
         write(fd,"o",1);
      }
   }
   else if (argc == 4 && !strcmp(argv[3], "x"))
   {
      printf("use lseek() & write\n");
      num_bytes = atoi(argv[2]);
      fd = open(argv[1], O_WRONLY|O_CREAT, 0666);
      if (fd == -1)
      {
         perror("cannot open!");
         exit(0);
      }
      int i;
      for(i = 0; i< num_bytes; i++)
      {
         lseek(fd,0,SEEK_END);
         write(fd,"o",1);
      }
   }
   close(fd);
   return 0;
   
}
 
cs

 

  1. 먼저 argument가 3개면 x를 쓰지 않았을 경우이므로 O_APPEND를 사용한다는 메시지를 출력

  2. atoi함수는 문자열로 입력한 숫자를 정수형 숫자로 바꿔주는 역할을 함

  3. num_byte에 몇 번이나 반복할지를 입력하는 것

  4. fd에 open을 사용하여 파일을 열거나 만듦 -> write only고 O_APPEND사용

  5. fd가 -1이면 에러메시지를 출력 후 프로그램 종료

  6. for문을 사용하여 num_bytes만큼 write를 반복 -> 'o'를 넣음

  7. argument가 4개이고 마지막 argument가 x라면 O_APPEND를 쓰지않고 위 과정을 실행

  8. 우선 O_APPEND를 사용하지 않고 lseek를 사용한다는 메시지를 출력한 뒤

  9. 위와 똑같이 atoi를 쓰고 fd에 open하는데 O_APPEND는 제외

  10. 에러 메시지도 똑같음

  11. for문에서 그냥 write를 썼던 위 과정과는 달리 이번에는 lseek로 다음에 쓸 위치를 찾는 과정을 넣어야 함

  12. lseek(fd,0,SEEK_END)는 SEEK_END 즉, 가장 마지막에서 +1을 한 자리에 offset을 정한다는 의미

  13. 모두 완료 되었으면 fd를 close함

 

  • 결과를 보면 O_APPEND를 사용했을 경우에는 크기가 설정한대로 잘 작성 되었지만 사용하지 않은 경우 누락된 'o'가 있음을 알 수 있음

  • 완전히 atomic한 시스템은 race condition이 일어나지 않음을 알 수 있음


 

tee 명령어와 유사한 mytee 프로그램을 작성하자

  • man 명령어를 통해 tee명령어의 사용법 확인 -> man 2 tee

  • cat input_file | tee output_file 이런 식으로 사용하면

    input_file의 내용이 출력됨과 동시에 output_file에 저장되는 명령어이다.

    input으로 파일을 쓰지 않고 ls l | tee output_file 이런 식으로 또 다른 명령어의 결과값을 input으로 줄 수도 있다.

 

  • 내가 만든 mytee 소스 코드와 실행 결과

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
 
#define SZ_BUF 1024
 
int main(int argc,char *argv[]){
        int fd;
 
        if(argc != 2){
                printf("mytee filename\n");
        }
        fd = open(argv[1],O_RDWR|O_CREAT|O_TRUNC,0666);
 
        if(fd == -1){
                perror("open");
                exit(0);
        }
        else{
                char *buffer[SZ_BUF];
                int nb;
 
                while(nb = read(0, buffer, SZ_BUF)){
                        write(fd, buffer ,nb);
                        write(1,buffer,nb);
                }
                printf("success\n");
                close(fd);
                exit(0);
        }
}
cs

 

 

  • 구현에 대한 간단한 설명

    1. 파이프라인으로 연결하여 넘겨준 인자는 argument에 속하는 것이 아닌 standard input으로 들어가기에 0이라는 숫자로 표현

    2. 따라서 mytee에 들어갈 argument는 명령어와 file이름 두 가지

    3. argument의 수가 2개가 아니라면 오류메시지를 출력 후 프로그램 종료

    4. 2개를 만족한다면 입력한 file이름을 open으로 열고 만약 파일이 존재하지 않는다면 생성, 그리고 open할 때마다 사이즈를 0으로 초기화 시켜줌/ 사용자, 그룹, 다른 사용자까지 읽고 쓸 수 있도록 설정

    5. 리턴값이 -1로 에러가 발생한다면 오류 메시지 출력 후 프로그램을 종료

    6. 버퍼 사이즈(1024로 정의)만큼의 buffer를 선언

    7. while문으로 파일이 모두 write되어 read값이 0이 될 때 까지 반복

    8. 읽은 값들을 fd(저장할 파일)에 write하면서 standard output에도 write

    9. 모두 완료되면 성공메시지를 띄우고 파일을 닫은 후 프로그램을 종료

+ Recent posts