왜 사용자 공간을 깨뜨리지 않는 Linux 커널 정책이 있습니까? 인 Linus Torvalds는

나는 Linux Kernel Mailing 목록에서 에티켓과 관련 하여이 문제에 대해 생각하기 시작했습니다. 세계에서 가장 잘 알려져 있고 틀림없이 가장 성공적이고 중요한 자유 소프트웨어 프로젝트 인 Linux 커널은 많은 압박을받습니다. 그리고 프로젝트 창립자이자 리더 인 Linus Torvalds는 여기서 소개 할 필요가 없습니다.

Linus는 때때로 LKML에서 화염으로 논란을 불러 일으킨다. 이러한 불꽃은 종종 자신의 입장에 따라 사용자 공간을 깨뜨리는 것과 관련이 있습니다. 내 질문에 나를 가져옵니다.

왜 사용자 공간을 깨뜨리는 것이 그렇게 나쁜지에 대한 역사적인 관점을 가질 수 있습니까? 내가 알기로, 사용자 공간을 깨 뜨리려면 응용 프로그램 수준에서 수정이 필요하지만 커널 코드를 개선하면 이것이 나쁜 것입니까?

내가 이해하는 것처럼 Linus의 명시된 정책은 사용자 공간을 깨뜨리지 않으면 코드 품질을 포함하여 다른 모든 것보다 우선한다는 것입니다. 이것이 중요한 이유는 무엇이며 그러한 정책의 장단점은 무엇입니까?

(Linus가 때때로이 주제에 대해 LKML의 최고 중위들과 의견을 달리하고 있기 때문에, 그러한 정책에 대해서는 분명히 일관된 정책이 적용되고있다.



답변

그 이유는 역사적인 것이 아니라 실제적인 것입니다. Linux 커널 위에서 실행되는 많은 프로그램이 많이 있습니다. 커널 인터페이스가 해당 프로그램을 중단하면 모든 사람이 해당 프로그램을 업그레이드해야합니다.

이제 대부분의 프로그램은 실제로 커널 인터페이스 ( 시스템 호출 )에 직접 의존하지 않고 C 표준 라이브러리 ( 시스템 호출 주위의 C 래퍼) 인터페이스에만 의존한다는 것이 사실 입니다. 그러나 어떤 표준 라이브러리입니까? Glibc? uClibC? Dietlibc? 바이오닉? 머슬? 기타

그러나 OS 별 서비스를 구현하고 표준 라이브러리에 의해 노출되지 않은 커널 인터페이스에 의존하는 많은 프로그램도 있습니다. (리눅스는 이들의 많은 통해 제공되는 /proc/sys.)

그리고 정적으로 컴파일 된 바이너리가 있습니다. 커널 업그레이드로 이들 중 하나가 중단되면 유일한 해결책은 다시 컴파일하는 것입니다. 소스가있는 경우 : Linux는 독점 소프트웨어도 지원합니다.

소스를 사용할 수있는 경우에도 모두 모으는 것은 어려울 수 있습니다. 특히 하드웨어 버그를 수정하기 위해 커널을 업그레이드 할 때 특히 그렇습니다. 사람들은 종종 하드웨어 지원이 필요하기 때문에 나머지 시스템과 독립적으로 커널을 업그레이드합니다. Linus Torvalds말에서 :

사용자 프로그램을 깨는 것은 용납되지 않습니다. 우리는 사람들이 오래된 바이너리를 수년 동안 사용한다는 것을 알고 있으며, 새로운 릴리스를 만든다고해서 그냥 버릴 수 있다는 것을 의미하지는 않습니다. 당신은 우리를 믿을 수 있습니다.

그는 이것을 강력한 규칙으로 만드는 한 가지 이유는 새로운 커널을 작동시키기 위해 다른 프로그램을 업그레이드해야 할뿐만 아니라 다른 프로그램과 다른 프로그램을 업그레이드 해야하는 종속성 지옥을 피하기 위해서 라고 설명 합니다. 모든 것이 특정 버전의 모든 것에 의존하기 때문입니다.

그건 어느 정도 잘 정의 된 편도 종속성이 괜찮습니다. 슬프지만 때로는 불가피합니다. (…) 좋지 않은 것은 양방향 의존성을 갖는 것입니다. 사용자 공간 HAL 코드가 새로운 커널에 의존한다면 괜찮습니다. 비록 사용자가 그것이 “금주의 커널”이 아니라 “지난 몇 달 동안의 커널”이되기를 바랍니다.

그러나 TWO-WAY 종속성이 있으면 문제가 생깁니다. 즉, 잠금 단계로 업그레이드해야하며 수락 할 수 없습니다. 사용자에게는 끔찍하지만, 더 중요한 것은 개발자에게 끔찍합니다. “버그가 발생했다”고 말할 수없고 이등분으로 좁히려 고 시도하는 것과 같은 일을하기 때문입니다.

사용자 공간에서 이러한 상호 종속성은 일반적으로 다른 라이브러리 버전을 유지하여 해결됩니다. 그러나 하나의 커널 만 실행할 수 있으므로 사람들이 원하는 모든 것을 지원해야합니다.

공식적 으로

[시스템 호출이 안정적으로 선언 됨]의 이전 버전과의 호환성은 2 년 이상 보장됩니다.

실제로는

syscall과 같은 대부분의 인터페이스는 절대 변경되지 않으며 항상 사용 가능합니다.

더 자주 변경되는 것은 하드웨어 관련 프로그램에서만 사용되는 인터페이스입니다 /sys. ( /proc반대로, /sys비 하드웨어 관련 서비스 용으로 도입 된 이후 로 호환되지 않는 방식으로 중단되지는 않습니다.)

요약하자면,

사용자 공간을 깨 뜨리려면 응용 프로그램 수준에서 수정이 필요합니다.

사람들이 나머지 시스템과 독립적으로 업그레이드하기를 원하는 커널이 하나 밖에 없기 때문에 나쁘지만 복잡한 상호 의존성을 가진 많은 응용 프로그램이 있습니다. 수백만 개의 다른 설정에서 수천 개의 응용 프로그램을 최신 상태로 유지하기 위해 커널을 안정적으로 유지하는 것이 더 쉽습니다.


답변

상호 의존적 시스템에는 기본적으로 두 가지 선택이 있습니다. 추상화 및 통합. (의도적으로 기술 용어를 사용하지 않습니다). Abstraction을 사용하면 API에 대한 코드가 변경 될 수 있지만 결과는 항상 동일하다는 API를 호출 할 수 있습니다. 예를 들어 전화를 걸 때 fs.open()네트워크 드라이브, SSD 또는 하드 드라이브인지는 신경 쓰지 않고 항상 열려있는 파일 설명자를 얻을 수 있습니다. “통합”의 목표는 방법이 바뀌더라도 일을하는 “최상의”방법을 제공하는 것입니다. 예를 들어, 파일을 여는 것은 디스크의 파일과 네트워크 공유의 경우 다를 수 있습니다. 두 가지 방법 모두 최신 Linux 데스크탑에서 광범위하게 사용됩니다.

개발자 관점에서는 “모든 버전에서 작동”또는 “특정 버전에서 작동”이라는 문제입니다. 이에 대한 좋은 예는 OpenGL입니다. 대부분의 게임은 특정 버전의 OpenGL에서 작동하도록 설정되어 있습니다. 소스에서 컴파일하는 것은 중요하지 않습니다. 게임이 OpenGL 1.1을 사용하도록 작성되었고 3.x에서 실행하려고한다면 좋은 시간이 없을 것입니다. 스펙트럼의 다른 쪽 끝에서 일부 호출은 무엇이든 작동 할 것으로 예상됩니다. 예를 들어, 나는 fs.open()어떤 커널 버전을 사용하고 싶지는 않지만 전화 하고 싶습니다. 파일 설명자가 필요합니다.

각 방법에는 이점이 있습니다. 통합은 이전 버전과의 호환성을 유지하면서 “최신”기능을 제공합니다. 추상화는 “최신”호출보다 안정성을 제공합니다. 중요하지는 않지만 중요하지는 않습니다.

공동의 관점에서 볼 때, 정말 좋은 이유가 없다면 복잡한 시스템에서는 추상화가 항상 더 좋습니다. 예를 들어 fs.open()커널 버전에 따라 다르게 작동 하는지 상상해보십시오 . 그런 다음 간단한 파일 시스템 상호 작용 라이브러리는 수백 가지의 “열린 파일”방법 (또는 아마도 블록)을 유지해야합니다. 새로운 커널 버전이 나오면 “업그레이드”할 수 없으며 사용한 모든 소프트웨어를 테스트해야합니다. 커널 6.2.2 (가짜)는 텍스트 편집기를 손상시킬 수 있습니다.

일부 실제 사례에서 OSX는 사용자 공간을 깨뜨리는 것에 신경 쓰지 않는 경향이 있습니다. 그들은 더 자주 “추상”보다 “통합”을 목표로합니다. 그리고 모든 주요 OS 업데이트에서 문제가 발생합니다. 한 가지 방법이 다른 방법보다 낫다는 것은 아닙니다. 선택과 디자인 결정입니다.

가장 중요한 것은 Linux 에코 시스템은 사람들이나 그룹이 자유 시간에 프로젝트를 수행하거나 도구가 유용하기 때문에 멋진 오픈 소스 프로젝트로 채워져 있다는 것입니다. 이를 염두에두고 재미를 멈추고 PIA가되기 시작하면 개발자들은 다른 곳으로 갈 것입니다.

예를 들어,에 패치를 제출했습니다 BuildNotify.py. 이타 적이기 때문이 아니라 도구를 사용하기 때문에 기능을 원했습니다. 쉬웠으므로 여기 패치가 있습니다. 복잡하거나 성 BuildNotify.py가시면 사용하지 않고 다른 것을 찾을 것입니다. 커널 업데이트가 텍스트 편집기에서 나올 때마다 다른 OS를 사용합니다. 커뮤니티에 대한 나의 기여는 (작지만 작음) 계속되거나 존재하지 않을 것입니다.

따라서 디자인 결정은 시스템 호출을 추상화하여 결정했을 때 fs.open()작동합니다. 그것은 인기 fs.openfs.open2()얻은 후에 오래 유지하는 것을 의미합니다 .

역사적으로 이것은 POSIX 시스템의 목표입니다. “여기에는 일련의 호출과 예상 반환 값이 있습니다. 중간을 찾으십시오.” 이식성의 이유로 다시 한 번. Linus가이 방법론을 사용하기로 선택한 이유는 그의 뇌 내부에 있으며, 그 이유를 정확히 알아야합니다. 그러나 그것이 저라면 복잡한 시스템의 통합보다 추상화를 선택합니다.


답변

디자인 결정과 선택입니다. Linus는 매우 드물고 예외적 인 (예 : 보안 관련) 상황을 제외하고 커널 변경으로 인해 응용 프로그램이 중단되지 않는 사용자 공간 개발자에게 보장 할 수 있기를 원합니다.

장점은 사용자 공간 개발자가 임의의 변덕스러운 이유로 새로운 커널에서 갑자기 코드를 깨뜨리지 않는다는 것입니다.

단점은 커널이 오래된 코드와 오래된 시스템 콜 등을 영원히 (또는 적어도 사용 날짜가 지난 것 이상) 유지해야한다는 것입니다.


답변