Tại sao có chính sách nhân Linux để không bao giờ phá vỡ không gian người dùng?


38

Tôi bắt đầu suy nghĩ về vấn đề này trong bối cảnh nghi thức trong danh sách Gửi thư hạt nhân Linux. Là dự án phần mềm miễn phí quan trọng và được cho là thành công nhất và được cho là nổi tiếng nhất thế giới, hạt nhân Linux nhận được rất nhiều báo chí. Và người sáng lập và lãnh đạo dự án, Linus Torvalds, rõ ràng không cần giới thiệu ở đây.

Linus thỉnh thoảng thu hút tranh cãi với ngọn lửa của mình trên LKML. Những ngọn lửa này thường xuyên, bằng sự thừa nhận của chính mình, để làm phá vỡ không gian người dùng. Điều này mang lại cho tôi câu hỏi của tôi.

Tôi có thể có một số quan điểm lịch sử về lý do tại sao phá vỡ không gian người dùng là một điều xấu như vậy? Theo tôi hiểu, việc phá vỡ không gian người dùng sẽ yêu cầu sửa lỗi ở cấp độ ứng dụng, nhưng đây có phải là một điều xấu, nếu nó cải thiện mã hạt nhân?

Theo tôi hiểu, chính sách đã nêu của Linus là không phá vỡ không gian người dùng hơn hẳn mọi thứ khác, kể cả chất lượng mã. Tại sao điều này rất quan trọng, và những ưu và nhược điểm của một chính sách như vậy là gì?

.


1
Bạn đã viết sai tên của Linus trong phần giới thiệu.
Ismael Miguel

Đó không phải là tôi chắc chắn, nhưng tôi đã quên upvote và bỏ phiếu ngay bây giờ.
Ismael Miguel

Câu trả lời:


38

Lý do không phải là một lịch sử mà là một thực tế. Có rất nhiều chương trình chạy trên kernel Linux; nếu một giao diện kernel phá vỡ các chương trình đó thì mọi người sẽ cần nâng cấp các chương trình đó.

Bây giờ đúng là hầu hết các chương trình trên thực tế không phụ thuộc trực tiếp vào giao diện kernel ( cuộc gọi hệ thống ), mà chỉ phụ thuộc vào giao diện của thư viện chuẩn C ( trình bao bọc C xung quanh các lệnh gọi hệ thống). Ồ, nhưng thư viện tiêu chuẩn nào? Glibc? uClibC? Ăn kiêng? Sinh học? Hồi giáo? v.v.

Nhưng cũng có nhiều chương trình triển khai các dịch vụ dành riêng cho hệ điều hành và phụ thuộc vào các giao diện kernel không được thư viện chuẩn trưng ra. (Trên Linux, nhiều trong số này được cung cấp thông qua /proc/sys.)

Và sau đó có các nhị phân được biên dịch tĩnh. Nếu nâng cấp kernel phá vỡ một trong những thứ này, giải pháp duy nhất sẽ là biên dịch lại chúng. Nếu bạn có nguồn: Linux cũng hỗ trợ phần mềm độc quyền.

Ngay cả khi nguồn có sẵn, thu thập tất cả có thể là một nỗi đau. Đặc biệt là khi bạn đang nâng cấp kernel của mình để sửa lỗi với phần cứng. Mọi người thường nâng cấp kernel của họ một cách độc lập với phần còn lại của hệ thống vì họ cần hỗ trợ phần cứng. Theo lời của Linus Torvalds :

Phá vỡ các chương trình người dùng đơn giản là không thể chấp nhận được. (Vắc) Chúng tôi biết rằng mọi người sử dụng các tệp nhị phân cũ trong nhiều năm và nhiều năm, và việc tạo ra một bản phát hành mới không có nghĩa là bạn có thể loại bỏ nó. Bạn có thể tin tưởng chúng tôi.

Ông cũng giải thích rằng một lý do để biến điều này thành một quy tắc mạnh mẽ là để tránh sự phụ thuộc vào địa ngục nơi bạn không chỉ phải nâng cấp một chương trình khác để có một số kernel mới hơn hoạt động mà còn phải nâng cấp một chương trình khác, và một chương trình khác , bởi vì mọi thứ phụ thuộc vào một phiên bản nhất định của mọi thứ.

một chút ổn khi có một phụ thuộc một chiều được xác định rõ. Thật buồn, nhưng đôi khi không thể tránh khỏi. (Hoài) Điều KHÔNG ổn là có sự phụ thuộc hai chiều. Nếu mã HAL không gian người dùng phụ thuộc vào một hạt nhân mới, điều đó không sao, mặc dù tôi nghi ngờ người dùng sẽ hy vọng rằng đó sẽ không phải là "hạt nhân của tuần", mà là "hạt nhân của vài tháng trước".

Nhưng nếu bạn có sự phụ thuộc HAI-CÁCH, bạn sẽ bị lừa. Điều đó có nghĩa là bạn phải nâng cấp theo từng bước và điều đó KHÔNG ĐƯỢC CHẤP NHẬN. Điều đó thật kinh khủng đối với người dùng, nhưng thậm chí quan trọng hơn, nó thật kinh khủng đối với các nhà phát triển, bởi vì điều đó có nghĩa là bạn không thể nói "một lỗi đã xảy ra" và làm những việc như cố gắng thu hẹp nó bằng cách chia đôi hoặc tương tự.

Trong không gian người dùng, những phụ thuộc lẫn nhau thường được giải quyết bằng cách giữ các phiên bản thư viện khác nhau; nhưng bạn chỉ có thể chạy một kernel, vì vậy nó phải hỗ trợ mọi thứ mọi người có thể muốn làm với nó.

Chính thức ,

khả năng tương thích ngược cho [các cuộc gọi hệ thống được tuyên bố ổn định] sẽ được đảm bảo trong ít nhất 2 năm.

Trong thực tế,

Hầu hết các giao diện (như tòa nhà chọc trời) dự kiến ​​sẽ không bao giờ thay đổi và luôn có sẵn.

Những gì thay đổi thường xuyên hơn là các giao diện chỉ được sử dụng bởi các chương trình liên quan đến phần cứng /sys. ( /procmặt khác, kể từ khi giới thiệu /sysđã được dành riêng cho các dịch vụ không liên quan đến phần cứng, khá nhiều thứ không bao giờ bị hỏng theo những cách không tương thích.)

Tóm tắt,

phá vỡ không gian người dùng sẽ yêu cầu sửa lỗi ở cấp độ ứng dụng

và điều đó thật tệ vì chỉ có một kernel, mà mọi người muốn nâng cấp độc lập với phần còn lại của hệ thống của họ, nhưng có rất nhiều ứng dụng ngoài kia với sự phụ thuộc lẫn nhau phức tạp. Việc giữ kernel ổn định là dễ dàng hơn để giữ cho hàng ngàn ứng dụng được cập nhật trên hàng triệu thiết lập khác nhau.


1
Cảm ơn bạn đã trả lời. Vì vậy, các giao diện được tuyên bố ổn định là một siêu bộ của các cuộc gọi hệ thống POSIX? Câu hỏi của tôi về lịch sử là cách thực hành này phát triển. Có lẽ các phiên bản gốc của nhân Linux đã không lo lắng về việc phá vỡ không gian người dùng, ít nhất là ban đầu.
Faheem Mitha

3
@FaheemMitha Vâng, họ đã làm, kể từ năm 1991 . Tôi không nghĩ rằng cách tiếp cận của Linus đã phát triển, đó luôn là các giao diện của các ứng dụng thông thường không thay đổi, các giao diện cho phần mềm được liên kết chặt chẽ với các thay đổi nhân rất hiếm khi xảy ra.
Gilles 'SO- ngừng trở nên xấu xa'

24

Trong bất kỳ hệ thống phụ thuộc lẫn nhau, về cơ bản có hai sự lựa chọn. Trừu tượng và hội nhập. (Tôi cố tình không sử dụng thuật ngữ kỹ thuật). Với Trừu tượng hóa, bạn đang nói rằng khi bạn thực hiện cuộc gọi tới API, trong khi mã đằng sau API có thể thay đổi, kết quả sẽ luôn giống nhau. Ví dụ: khi chúng tôi gọi, fs.open()chúng tôi không quan tâm đó là ổ đĩa mạng, ổ SSD hay ổ cứng, chúng tôi sẽ luôn nhận được một bộ mô tả tệp mở mà chúng tôi có thể làm được. Với "tích hợp", mục tiêu là cung cấp cách "tốt nhất" để thực hiện một việc, ngay cả khi cách thay đổi. Ví dụ: mở tệp có thể khác đối với chia sẻ mạng so với tệp trên đĩa. Cả hai cách đều được sử dụng khá nhiều trong máy tính để bàn Linux hiện đại.

Từ quan điểm của các nhà phát triển, đó là một câu hỏi "hoạt động với bất kỳ phiên bản nào" hoặc "hoạt động với một phiên bản cụ thể". Một ví dụ tuyệt vời về điều này là OpenGL. Hầu hết các trò chơi được thiết lập để hoạt động với một phiên bản cụ thể của OpenGL. Không thành vấn đề nếu bạn biên dịch từ nguồn. Nếu trò chơi được viết để sử dụng OpenGL 1.1 và bạn đang cố gắng để nó chạy trên 3.x, bạn sẽ không có thời gian tốt. Ở phía bên kia của quang phổ, một số cuộc gọi, dự kiến ​​sẽ hoạt động bất kể điều gì. Ví dụ, tôi muốn gọi fs.open()tôi không muốn quan tâm tôi đang dùng phiên bản kernel nào. Tôi chỉ muốn một mô tả tập tin.

Có những lợi ích cho mỗi cách. Tích hợp cung cấp các tính năng "mới hơn" với chi phí tương thích ngược. Trong khi trừu tượng hóa cung cấp sự ổn định đối với các cuộc gọi "mới hơn". Mặc dù điều quan trọng cần lưu ý đó là vấn đề ưu tiên, không phải là khả năng.

Từ quan điểm chung, không có lý do thực sự tốt, sự trừu tượng luôn tốt hơn trong một hệ thống phức tạp. Ví dụ, hãy tưởng tượng nếu fs.open()làm việc khác nhau tùy thuộc vào phiên bản kernel. Sau đó, một thư viện tương tác hệ thống tệp đơn giản sẽ cần duy trì hàng trăm phương thức "mở tệp" khác nhau (hoặc có thể là các khối). Khi một phiên bản kernel mới xuất hiện, bạn sẽ không thể "nâng cấp", bạn sẽ phải kiểm tra từng phần mềm bạn đã sử dụng. Kernel 6.2.2 (giả) có thể phá vỡ trình soạn thảo văn bản của bạn.

Đối với một số ví dụ trong thế giới thực, OSX có xu hướng không quan tâm đến việc phá vỡ Không gian người dùng. Họ nhắm đến "tích hợp" hơn "trừu tượng" thường xuyên hơn. Và tại mỗi bản cập nhật hệ điều hành lớn, mọi thứ đều bị phá vỡ. Điều đó không có nghĩa là cách này tốt hơn cách khác. Đó là một sự lựa chọn và quyết định thiết kế.

Quan trọng nhất, hệ sinh thái Linux chứa đầy các dự án mã nguồn mở tuyệt vời, nơi mọi người hoặc các nhóm làm việc với dự án trong thời gian rảnh hoặc vì công cụ này hữu ích. Với ý nghĩ đó, thứ hai nó ngừng vui vẻ và bắt đầu là một PIA, những nhà phát triển đó sẽ đi đến một nơi khác.

Ví dụ, tôi đã gửi một bản vá cho BuildNotify.py. Không phải vì tôi vị tha, mà vì tôi sử dụng công cụ này và tôi muốn có một tính năng. Thật dễ dàng, vì vậy ở đây, có một bản vá. Nếu nó phức tạp hoặc cồng kềnh, tôi sẽ không sử dụng BuildNotify.pyvà tôi sẽ tìm thứ khác. Nếu mỗi lần cập nhật kernel xuất hiện trình soạn thảo văn bản của tôi bị hỏng, tôi sẽ chỉ sử dụng một hệ điều hành khác. Những đóng góp của tôi cho cộng đồng (dù nhỏ) sẽ không tiếp tục hoặc tồn tại, v.v.

Vì vậy, quyết định thiết kế được đưa ra cho các cuộc gọi hệ thống trừu tượng, để khi tôi thực hiện fs.open()nó chỉ hoạt động. Điều đó có nghĩa là duy trì fs.openlâu sau khi fs.open2()nổi tiếng.

Trong lịch sử, đây là mục tiêu của các hệ thống POSIX nói chung. "Đây là một tập hợp các cuộc gọi và giá trị trả về dự kiến, bạn tìm ra giữa." Một lần nữa vì lý do tính di động. Tại sao Linus chọn sử dụng phương pháp đó là nội bộ trong não của anh ta, và bạn sẽ phải hỏi anh ta để biết chính xác tại sao. Tuy nhiên, nếu là tôi, tôi sẽ chọn sự trừu tượng hóa tích hợp trên một hệ thống phức tạp.


1
API cho không gian người dùng, API của tòa nhà, được xác định rõ (đặc biệt là tập hợp con POSIX) và ổn định, vì loại bỏ bất kỳ phần nào trong đó sẽ phá vỡ phần mềm mà mọi người có thể đã cài đặt. Những gì nó không có là API trình điều khiển ổn định .
pjc50

4
@FaheemMitha, đó là cách khác. Các nhà phát triển kernel có thể tự do phá vỡ trình điều khiển API bất cứ khi nào họ muốn, miễn là họ sửa tất cả các trình điều khiển trong kernel trước khi phát hành tiếp theo. Nó phá vỡ API không gian người dùng hoặc thậm chí thực hiện những thứ không phải API có thể phá vỡ không gian người dùng, tạo ra các phản ứng sử thi từ Linus.
Đánh dấu

4
Ví dụ: nếu ai đó quyết định thay đổi nó bằng cách trả lại mã lỗi khác từ ioctl () trong một số trường hợp: lkml.org/lkml/2012/12/23/75 (có chửi thề và tấn công cá nhân vào nhà phát triển chịu trách nhiệm). Bản vá đó đã bị từ chối vì nó sẽ phá vỡ PulseAudio và do đó tất cả âm thanh trên các hệ thống Gnome.
pjc50

1
@FaheemMitha, về cơ bản, def add (a, b); trả về a + b; kết thúc --- def thêm (a, b); c = a + b; trả lại c; kết thúc --- def thêm (a, b); c = a + b +10; trả lại c - 10; kết thúc - là tất cả các triển khai "giống nhau" của add. Điều khiến anh ấy khó chịu là khi mọi người làm def thêm (a, b); trả về (a + b) * -1; Về bản chất, việc thay đổi cách mọi thứ "bên trong" thành kernel hoạt động là ổn. Thay đổi những gì được trả lại cho một lệnh gọi API "công khai" đã xác định là không. Có hai loại lệnh gọi API "riêng tư" và "công khai". Ông cảm thấy rằng các cuộc gọi API công khai không bao giờ nên thay đổi mà không có lý do chính đáng.
coteyr

3
Một ví dụ không mã; Bạn đến cửa hàng, bạn mua xăng 87 Octane. Bạn, với tư cách là người tiêu dùng không "quan tâm" nguồn khí đến từ đâu hoặc cách xử lý. Bạn chỉ cần quan tâm đến việc nhận khí của bạn. Nếu khí trải qua một quá trình tinh chế khác, bạn không quan tâm. Chắc chắn quá trình tinh chế có thể thay đổi. Thậm chí có nhiều nguồn dầu khác nhau. Nhưng những gì bạn quan tâm là nhận được khí 87 Octane. Vì vậy, vị trí của anh ta, là thay đổi nguồn, thay đổi nhà máy lọc dầu, thay đổi những gì đã từng, miễn là thứ phát ra từ máy bơm là khí 87 Octane. Tất cả những thứ "đằng sau hậu trường" không thành vấn đề. Miễn là có 87 khí Octane.
coteyr

8

Đó là một quyết định thiết kế và lựa chọn. Linus muốn có thể đảm bảo với các nhà phát triển không gian người dùng rằng, ngoại trừ trong các trường hợp cực kỳ hiếm gặp và đặc biệt (ví dụ liên quan đến bảo mật), các thay đổi trong kernel sẽ không phá vỡ các ứng dụng của họ.

Ưu điểm là các nhà phát triển không gian người dùng sẽ không tìm thấy mã của họ đột nhiên phá vỡ các nhân mới vì những lý do tùy tiện và thất thường.

Nhược điểm là hạt nhân phải giữ mã cũ và các tòa nhà cũ v.v ... mãi mãi (hoặc, ít nhất, đã qua ngày sử dụng của chúng).


Cảm ơn bạn đã trả lời. Bạn có biết về lịch sử của quyết định này phát triển như thế nào không? Tôi biết các dự án có quan điểm hơi khác. Ví dụ, dự án Mercurial không có API cố định và có thể và phá vỡ mã dựa trên nó.
Faheem Mitha

Không, xin lỗi, tôi không thể nhớ nó đã diễn ra như thế nào. Bạn có thể gửi email cho Linus hoặc LKML và hỏi anh ấy.
cas

2
Mercurial không phải là một hệ điều hành. Toàn bộ quan điểm của một hệ điều hành là cho phép chạy phần mềm khác trên phần mềm và phá vỡ phần mềm khác đó là rất không phổ biến. Khi so sánh, Windows cũng đã duy trì khả năng tương thích ngược trong một thời gian rất dài; Mã Windows 16 bit chỉ bị lỗi thời gần đây.
pjc50

@ pjc50 Đúng là Mercurial không phải là một hệ điều hành, nhưng không phân biệt, có phần mềm khác, ngay cả khi chỉ kịch bản, mà phụ thuộc vào nó. Và có khả năng có thể bị phá vỡ bởi những thay đổi.
Faheem Mitha
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.