방금 새 파일을 생성하기 위해 명령을 사용하는 요령을 배웠습니다 cat
. 제가 테스트한 바에 따르면 마지막 줄 뒤에 개행 문자가 없으면 ctrl+d아래와 같이 두 번 입력해야 입력이 완료됩니다.
[root@192 ~]# 고양이 > 테스트 ㅏ 두번째 ctrl+d[root@192 ~]# 고양이 > 테스트 ㅏ b ctrl+dctrl+d[루트@192 ~]#
이것이 예상되는가? 왜 이런 문제가 발생합니까?
답변1
예, 예상됩니다.
우리는 Ctrl-D가 cat
입력에서 "파일 끝"을 확인한 다음 읽기를 중지하고 종료한다고 말하지만 사실은 아닙니다. 이것은 터미널에 있기 때문에 실제 "끝"이 없으며 실제로 "파일 끝"이 아닙니다.한 번감지되었지만 read()
0바이트가 없습니다.
일반적으로 read()
시스템 호출은 파일 끝과 같이 더 이상 사용할 수 있는 바이트가 없는 것으로 확인되지 않는 한 0바이트를 반환하지 않습니다. 사용 가능한 데이터가 없는 네트워크 소켓에서 읽을 때 새로운 데이터가 어느 시점에 도착할 것으로 예상되므로 시스템 호출은 0바이트를 읽는 대신 차단하고 일부 데이터가 도착할 때까지 기다리거나 방지할 것이라는 오류를 반환합니다. 연결이 닫히면 0바이트를 반환합니다. 그런 다음 파일에서도 마지막(또는 과거) 읽기가 끝없이 최종적이지는 않습니다. 다른 프로세스가 파일에 무언가를 써서 파일을 더 길게 만들 수 있고 그 후에 새로운 읽기 시도가 더 많은 데이터를 반환할 수 있기 때문입니다. (이것은 간단한 구현이 tail -f
수행하는 작업입니다.)
많은 사용 사례에서 "0바이트 읽기"를 "파일 끝이 감지됨"으로 생각하는 것은 실제로는 동일한 것으로 간주될 만큼 충분히 잘 작동합니다.
여기서 Ctrl-D가 하는 일은 터미널 드라이버에게 완전한 라인이 아니더라도 지금까지 주어진 모든 것을 전달하도록 지시하는 것입니다. 줄 시작 부분에서 모든 0바이트는 EOF로 감지됩니다. 그러나 문자 다음에 b
첫 번째 Ctrl-D가 전송되고 b
0바이트가 입력된 후에 다음 문자가 전송되어 b
이제 EOF로 감지됩니다.
cat
리디렉션 없이 실행하면 어떤 일이 발생하는지 확인할 수도 있습니다 . 내가 이탤릭체로 입력한 내용은 다음과 같습니다.
$고양이 부자Ctrl-D부자
Ctrl-D를 누르면 cat
입력을 받아 foo
다시 인쇄하고 입력을 계속 기다립니다. 줄은 다음과 같으며 foofoo
그 뒤에 개행 문자가 없으므로 커서가 끝에 남아 있습니다.
답변2
몇 마디만 해주세요.
제가 아는 한, 간단히 살펴보면소스 코드, cat
버퍼를 사용하여 작업 흐름을 최적화합니다. cat
특별한 명령줄 옵션 없이 표준 입력에서 간단한 호출 동작을 참조하면 다음과 같습니다 .
- 버퍼가 비어 있으면 하나의 Ctrl+ D만으로 종료할 수 있습니다.
- 그렇지 않은 경우 첫 번째 Ctrl-D 필수 버퍼덤프(비어짐), 두 번째는 종료 명령으로 해석됩니다.
즉, 실행 cat> test
하고 간단히 입력 하면 Ctrl-D 현재 디렉터리에 빈 파일(이름이 지정된)이 생성되거나 test
파일이 이미 존재하는 경우 두 번째 파일이 필요 없이 파일이 비워집니다 Ctrl-D .
이 질문의 범위를 벗어나지만 그리 멀지는 않습니다. 터미널/셸 인스턴스에 문자를 보내는 경우 불필요한 두 번째로 인해 Ctrl-D불필요한 종료가 발생할 수 있습니다(주로 위의 예와 관련됨).