리눅스 cp 중단 - linugseu cp jungdan

source-filetarget-file 로 복사하는 명령이다. 만약 target-file 이 존재하지 않는다면, cp는 새로 파일을 만든다. 만약 파일이 있다면, 기존 파일의 내용을 source-file 의 내용으로 바꾼다. 이를 위해서, 파일을 생성하고 쓰는 법을 알아야 한다.

1. sourcefile을 읽기로 연다. 2. copyfile을 쓰기로 연다. 3. source에서 buffer로 EOF를 만날 때까지 읽는다. 4. buffer에서 copy로 쓴다. 5. sourcefile과 copyfile을 닫는다.0, 1. sourcefile을 읽기로 연다. 2. copyfile을 쓰기로 연다. 3. source에서 buffer로 EOF를 만날 때까지 읽는다. 4. buffer에서 copy로 쓴다. 5. sourcefile과 copyfile을 닫는다.1 API

파일 생성: 1. sourcefile을 읽기로 연다. 2. copyfile을 쓰기로 연다. 3. source에서 buffer로 EOF를 만날 때까지 읽는다. 4. buffer에서 copy로 쓴다. 5. sourcefile과 copyfile을 닫는다.0

  • 파일을 생성하거나 비운다.
  • 1. sourcefile을 읽기로 연다.
    2. copyfile을 쓰기로 연다.
    3. source에서 buffer로 EOF를 만날 때까지 읽는다.
    4. buffer에서 copy로 쓴다.
    5. sourcefile과 copyfile을 닫는다.
    3 에 위치한다.
  • 다음과 같이 사용할 수 있다.
  • 만약 파일이 존재하지 않으면,
    1. sourcefile을 읽기로 연다.
    2. copyfile을 쓰기로 연다.
    3. source에서 buffer로 EOF를 만날 때까지 읽는다.
    4. buffer에서 copy로 쓴다.
    5. sourcefile과 copyfile을 닫는다.
    4 에 따라 권한을 부여해 파일을 생성한다.
  • 만약 파일이 존재하면, 파일을 비운다. 단, 권한은 바뀌지 않는다.

파일 쓰기: 1. sourcefile을 읽기로 연다. 2. copyfile을 쓰기로 연다. 3. source에서 buffer로 EOF를 만날 때까지 읽는다. 4. buffer에서 copy로 쓴다. 5. sourcefile과 copyfile을 닫는다.1

  • 메모리에서 파일로 데이터를 보낸다.
  • 1. sourcefile을 읽기로 연다.
    2. copyfile을 쓰기로 연다.
    3. source에서 buffer로 EOF를 만날 때까지 읽는다.
    4. buffer에서 copy로 쓴다.
    5. sourcefile과 copyfile을 닫는다.
    6 에 위치한다.
  • 다음과 같이 사용할 수 있다.

이제 파일을 생성하고 쓸 수 있으니, cp 를 작성해보자.

1. sourcefile을 읽기로 연다. 2. copyfile을 쓰기로 연다. 3. source에서 buffer로 EOF를 만날 때까지 읽는다. 4. buffer에서 copy로 쓴다. 5. sourcefile과 copyfile을 닫는다.8

pseudo 코드를 먼저 작성해보자.

1. sourcefile을 읽기로 연다.
2. copyfile을 쓰기로 연다.
3. source에서 buffer로 EOF를 만날 때까지 읽는다.
4. buffer에서 copy로 쓴다.
5. sourcefile과 copyfile을 닫는다.

이제 코드를 작성해보자.

파일 permission

위 코드에서,

1. sourcefile을 읽기로 연다.
2. copyfile을 쓰기로 연다.
3. source에서 buffer로 EOF를 만날 때까지 읽는다.
4. buffer에서 copy로 쓴다.
5. sourcefile과 copyfile을 닫는다.
9 라는 매크로를 cp0 로 선언하여 파일을 생성하는 것을 알 수 있다. 이게 뭘 의미하는 걸까?

먼저, linux permission에는 cp1, cp2, cp3 3가지 종류가 있다. cp1 은 Readable (읽기가 가능), cp2는 Writable (쓰기가 가능), cp3는 eXecutable (실행이 가능)를 의미한다. cp7 을 통해 파일의 permission을 볼 수 있다. 명령어를 한 번 입력 해보자.

리눅스 cp 중단 - linugseu cp jungdan

cp8 나 cp9 와 같이 cp1, cp2, cp3 로 이루어진 것은 알겠는데, 요상하게 생기긴 했다. cp3 를 예시로 들어보자. 일단 세 자리씩 끊어서 보면 cp4, cp4, cp6 이다. 이는 해당 파일이 소유자는 cp4, 파일의 소유 그룹에 속한 사용자는 cp4, 나머지는 cp6이 가능하다는 것을 의미하며 cp0는 해당 permission이 없다는 기호다. 그렇다면 cp8 는 소유자는 cp2, 그룹은 cp2, 공개는 cp4 의 permission을 가진다는 뜻이다.

그렇다면 cp0 는 무엇을 의미할까? cp0 의 각 자릿수를 2진수로 나타내면 cp7 은 110, cp8 는 100, cp9 는 100이다. 1은 permission이 부여 된다는 것을, 0은 부여되지 않는다는 것을 의미한다. 즉 cp0는 cp1 를 의미하는 것이다. 이렇게 linux에서는 숫자를 통해 해당 파일의 permission을 나타낼 수 있다.

I/O Buffering

하지만 아직 효율성에 대한 문제가 남았다. 바로 buffer의 크기와 관련된 문제이다. 예를 들어서 위 코드에서는 buffer의 크기를 cp2 로 잡았다. 즉 sourcefile에서 copyfile로 한 번에 cp2 만을 옮길 수 있다는 것이다. 즉 sourcefile의 크기가 커질 수록, sourcefile에서 copyfile로 옮기는 과정의 반복 횟수가 증가한다는 뜻이다. 이는 system call의 반복 횟수가 증가한다는 뜻이고, 이로 인해 많은 시간이 소요하게 된다.

System call의 횟수가 왜 시간에 영향을 줄까?

바로 user mode와 kernel mode 사이의 mode change에 걸리는 시간 때문이다. CPU는 특별한 stack과 메모리 환경을 가지는 kernel mode에서 kernel code를 실행하고, user code를 실행할 때는 user mode에서 실행한다.

1. sourcefile을 읽기로 연다.
2. copyfile을 쓰기로 연다.
3. source에서 buffer로 EOF를 만날 때까지 읽는다.
4. buffer에서 copy로 쓴다.
5. sourcefile과 copyfile을 닫는다.
0,
1. sourcefile을 읽기로 연다.
2. copyfile을 쓰기로 연다.
3. source에서 buffer로 EOF를 만날 때까지 읽는다.
4. buffer에서 copy로 쓴다.
5. sourcefile과 copyfile을 닫는다.
1 와 같은 system call을 통해 kernel mode로 들어가 kernel code를 실행한 후 다시
1. sourcefile을 읽기로 연다.
2. copyfile을 쓰기로 연다.
3. source에서 buffer로 EOF를 만날 때까지 읽는다.
4. buffer에서 copy로 쓴다.
5. sourcefile과 copyfile을 닫는다.
8 의 나머지 코드, 즉 user code를 실행하기 위해 user mode로 돌아오는 과정이 시간을 소모하게 되는 것이다.

리눅스 cp 중단 - linugseu cp jungdan

Kernel

kernel은 올바른 동작을 위한 OS의 중요한 부분이다. kernel mode에서 실행되며, user mode에서 kernel mode로 변환되기 위해 trap instruction이 사용된다.

  • trap 또는 exception은 프로그램이 생성하는 중단이며, 에러나 사용자의 요청에 의해 발생된다. (division by zero, OS 시스템 서비스의 요청 등)

그렇다면, 어떻게 더 효율적이게

1. sourcefile을 읽기로 연다.
2. copyfile을 쓰기로 연다.
3. source에서 buffer로 EOF를 만날 때까지 읽는다.
4. buffer에서 copy로 쓴다.
5. sourcefile과 copyfile을 닫는다.
8 의 코드를 짤 수 있을까? 예를 들면, 한 번에 많은 양의 데이터를 읽은 후 로컬 저장소에 하나씩 저장해 처리하는 것이다. 그렇다면 system call을 반복하는 횟수를 줄일 수 있을 것이다. 이는 cp8 에도 적용될 수 있다. cp9 파일을 한 번에 읽은 후 배열에 저장하여 처리한다면 속도를 개선할 수 있을 것이다.

Kernel Buffering

buffering을 통해 효율적인 프로그램을 짤 수 있었다. 그렇다면, 이렇게 좋은 buffering을 kernel도 사용하고 있을까?

물론이다. kernel 또한 디스크의 일정 부분을 복사 해놓은 kernel buffer라는 것을 가지고 있어서 효율적인 I/O 처리를 하고 있다. source-file0 를 호출하면 kernel buffer에서 데이터를 복사하고,

1. sourcefile을 읽기로 연다.
2. copyfile을 쓰기로 연다.
3. source에서 buffer로 EOF를 만날 때까지 읽는다.
4. buffer에서 copy로 쓴다.
5. sourcefile과 copyfile을 닫는다.
1 를 호출하면 프로세서에서 kernel buffer로 데이터를 복사한다.