1 điểm bởi GN⁺ 3 giờ trước | 1 bình luận | Chia sẻ qua WhatsApp
  • Trên Windows vẫn còn tồn tại cả TMPTEMP để chỉ vị trí tệp tạm, và khi hai biến này khác nhau thì biến nào được dùng sẽ phụ thuộc vào cách từng chương trình được triển khai
  • CP/M không có biến môi trường, nên vị trí tệp tạm phải được cấu hình riêng cho từng chương trình; các chương trình như WordStar dùng cách vá các byte cụ thể trong tệp thực thi để thay đổi hành vi
  • MS-DOS bổ sung biến môi trường trong khi vẫn rất chú trọng tính tương thích với CP/M, nhưng các chương trình MS-DOS thời kỳ đầu hầu như không dùng TEMP hay TMP do quán tính từ CP/M trước đó
  • Khi các chương trình MS-DOS bắt đầu dùng biến môi trường như một cách lưu cấu hình, TEMPTMP cạnh tranh với nhau; một số chương trình như DISKCOPYEDIT tìm TEMP trước TMP
  • Cơ chế pipe của MS-DOS 2.0 chọn TEMP cho vị trí tệp tạm, nhưng GetTempFileName của Windows lại kiểm tra TMP trước, khiến hai biến này tiếp tục cùng tồn tại

Bối cảnh vì sao cả TMPTEMP đều còn tồn tại

  • Trong các biến môi trường Windows, cả TMPTEMP đều tồn tại để chỉ định vị trí tệp tạm; nếu hai biến này khác nhau thì biến nào là đúng sẽ tùy vào từng chương trình
  • Việc một chương trình tạo tệp tạm ở đâu phụ thuộc vào cách chương trình đó được triển khai; các chương trình Windows nhiều khả năng dùng hàm GetTempFileName, và trong trường hợp này TMP được ưu tiên
  • Lý do hộp thoại thiết lập biến môi trường hiển thị cả TMPTEMP là vì chưa từng có một chuẩn duy nhất hoàn toàn thắng thế, mà về mặt lịch sử các lựa chọn khác nhau đã cùng tồn tại

CP/M không có biến môi trường

  • Vào khoảng năm 1973, hệ điều hành phổ biến trên máy vi tính là CP/M, và CP/M không có biến môi trường
  • Vì không có biến môi trường nên cũng không tồn tại biến môi trường TMP hay TEMP
  • Muốn chỉ định nơi lưu tệp tạm cho một chương trình thì phải cấu hình riêng cho từng chương trình, chẳng hạn vá một byte cụ thể trong tệp thực thi để chỉ định ký tự ổ đĩa đặt tệp tạm
  • Các chương trình như WordStar ghi trong tài liệu hướng dẫn rằng vá byte nào sẽ thay đổi hành vi nào, đồng thời còn cung cấp cả vùng vá để chèn các tiểu trình tùy biến như hỗ trợ máy in

Sự xuất hiện của MS-DOS và biến môi trường

  • Năm 1981, bộ xử lý 8086 và MS-DOS ra đời, và cả hai đều chịu ảnh hưởng rất mạnh từ CP/M
  • Một trong những mục tiêu thiết kế ban đầu của MS-DOS là cho phép dịch cơ học các chương trình CP/M cho bộ xử lý 8080 sang chương trình MS-DOS cho bộ xử lý 8086
  • Trình dịch này giả định rằng chương trình không dùng các kiểu bất thường như mã tự sửa, nhảy vào giữa lệnh, hay dùng mã như dữ liệu
  • Các thanh ghi H và L của 8080 tương ứng với các thanh ghi BH và BL của 8086, và việc trên 8080 chỉ có HL dùng được để truy cập địa chỉ đã tính toán là lý do trên 8086, trong AX, BX, CX, DX thì chỉ có BX dùng được cho truy cập bộ nhớ
  • Ngoài tính tương thích với CP/M, MS-DOS còn bổ sung biến môi trường; tuy vậy, vì các chương trình CP/M cũ không dùng biến môi trường nên các chương trình MS-DOS ban đầu cũng không dùng chúng
  • Người dùng có thể thiết lập TEMP hay TMP, nhưng các chương trình thời kỳ đầu không để ý đến điều đó

TEMPTMP cạnh tranh trên thị trường

  • Theo thời gian, khi các chương trình được viết chủ yếu cho MS-DOS xuất hiện, chúng bắt đầu dùng biến môi trường như một nơi lưu dữ liệu cấu hình
  • TEMPTMP lần lượt bắt đầu được dùng làm biến môi trường chỉ vị trí tệp tạm, và cả hai trở thành những ứng viên chính
  • Việc kiểm tra biến nào trước là một lựa chọn phụ thuộc vào cách triển khai của từng chương trình
  • Nhiều chương trình kiểm tra cả hai để làm hài lòng cả hai phía, nhưng việc nhìn biến nào trước thì khác nhau tùy từng triển khai
  • Các chương trình DISKCOPYEDIT đời cũ tìm TEMP trước TMP

Pipe của MS-DOS 2.0 và TEMP

  • MS-DOS 2.0 giới thiệu tính năng pipe để chuyển đầu ra của một chương trình thành đầu vào của chương trình khác
  • Vì MS-DOS là hệ điều hành đơn nhiệm, pipe được mô phỏng bằng cách chuyển hướng đầu ra của chương trình thứ nhất vào một tệp tạm, chạy nó đến hết, rồi chạy chương trình thứ hai để đọc đầu vào từ tệp tạm đó
  • Vì tính năng này mà bản thân MS-DOS cũng cần một nơi để tạo tệp tạm
  • TEMP được chọn làm biến điều khiển vị trí của tệp tạm đó
  • COMMAND.COM chọn TEMP, việc các chương trình khác dùng TEMP hay TMP vẫn là lựa chọn riêng của từng chương trình

Trên Windows, hình thành một lộ trình ưu tiên TMP

  • Windows cũng trải qua quá trình tương tự, nhưng cách triển khai ban đầu của GetTempFileName được tạo ra để kiểm tra TMP trước TEMP
  • Khi chương trình Windows tạo tệp tạm bằng GetTempFileName, nó sẽ có xu hướng ưu tiên TMP hơn
  • Vì vậy không có một câu trả lời duy nhất cho câu hỏi “biến nào mới đúng”, mà còn tùy chương trình dùng API nào hay logic riêng nào
  • Đến nay, hộp thoại thiết lập biến môi trường vẫn còn hiển thị cả TMPTEMP, và hai biến này tiếp tục cùng tồn tại để chỉ vị trí tệp tạm

1 bình luận

 
Ý kiến trên Hacker News
  • Thú vị thật. Đây là chuyện có từ trước thời của tôi nên tôi chưa từng nghe việc cấu hình chương trình CP/M bằng bản vá

    • Đúng vậy, thực sự đã có cách đó, và mã vá phải là mã máy Z80/8080
      Tôi từng tự viết các routine xuất bàn phím và màn hình nhanh hơn cho WordStar của mình bằng tính năng này
    • Đúng vậy, chuyện đó có thật, và một số chương trình vốn là chương trình CP/M vẫn tồn tại rất lâu, đến cả WordStar 7.0 cho DOS
      Tôi nhớ tài liệu WordStar 7 có bao gồm các vị trí vá có thể dùng với debug.exe của DOS để thay đổi hành vi chương trình
    • Bây giờ vẫn còn tồn tại ở một mức độ nào đó. Những thứ do suckless làm thường được cấu hình bằng cách sửa config.h rồi biên dịch lại
      https://suckless.org/
      Nói thêm là tôi chỉ vừa nhận ra chuyện này đã được nhắc tới ở một nhánh con khác trong trang này
    • Cách đó là cần thiết vì RAM và dung lượng đĩa khi ấy cực kỳ hạn chế, và gần như mọi máy tính đều đi kèm assembler
      Nhiều chương trình CP/M phải chạy được trên 32K RAM và đĩa mềm 130K chậm chạp, thậm chí tệ hơn là băng cassette. Có 64K RAM và đĩa 360K đã là khá đặc biệt
      Hồi đó, khác với ngày nay, người ta tối ưu chương trình theo mức thấp nhất của thị trường chứ không phải mức cao nhất. Chạy được trên càng nhiều hệ thống thì bán được càng nhiều, và không đẩy việc nâng cấp phần cứng sang cho khách hàng
      Đơn giản là không có chỗ cho file cấu hình ngoài hay chương trình tạo ra file cấu hình đó, và ngay cả việc xử lý tham số dòng lệnh cũng tốn những byte rất quý giá
      Ngày nay người ta than phiền MacBook Neo chỉ có 8,000,000,000 byte RAM, nhưng năm 1978 người ta vẫn có thể làm ra một IDE cơ bản chỉ 2,048 byte
  • Tôi thích blog của Raymond, nhưng nói rằng CP/M đã phổ biến trên microcomputer vào năm 1973 thì nghe kỳ lạ
    Microcomputer năm 1973 gần như chỉ là các nguyên mẫu ở mức hệ thống phát triển như Intel Intellec, và không có hệ điều hành. Đúng là Kildall bắt đầu phát triển CP/M vào năm 1973, nhưng lúc đó nó chỉ chạy trên trình mô phỏng của mainframe PDP-10
    Nếu là 1979 thì còn được, chứ 1973 là sớm quá

    • Wikipedia ghi rằng CP/M được tạo ra vào năm 1974, nên mốc thời gian ở đây rõ ràng là lệch
    • Thú vị ở chỗ khoảng cách giữa 1979 và 1973 cũng bằng khoảng cách giữa năm 2020 và hiện tại
      Nghĩ vậy mới thấy năm 2020 thậm chí còn chưa có ChatGPT
  • Đây là ví dụ điển hình cho việc một quyết định mà lập trình viên ban đầu đưa ra gần như không suy nghĩ lại có thể tồn tại hàng chục năm

    • Một bảng cốt lõi trong sản phẩm thuộc S&P500 mà tôi từng đụng tới sẽ mãi mãi mang tên attornies. Đơn giản vì chẳng ai bắt được lỗi chính tả đó ở giai đoạn đầu
    • Không gì vĩnh viễn bằng một quyết định TMPorary
  • Khả năng cao các chương trình chọn TMP vì phần mở rộng tệp trong MS-DOS tối đa chỉ có 3 ký tự, và theo thông lệ người ta dùng phần mở rộng .TMP cho tên tệp tạm

  • Cũng giống như việc các chương trình Unix không nhất quán trong chuyện nhìn http_proxy hay HTTP_PROXY
    Ngày nay nhiều chương trình xem cả hai, nhưng thứ tự kiểm tra có thể không giống nhau

  • Đoạn nhắc đến CP/M gây khó hiểu. Tác giả có vẻ nói nó sẽ quan trọng về sau, rồi cuối cùng lại giải thích rằng nó không liên quan gì đến CP/M hay CPU 8080

    • Đồng ý. Câu chuyện này chẳng liên quan mấy đến CP/M, cũng chẳng liên quan đến nhánh rẽ sang 8080/8086
      Mấu chốt chỉ là Microsoft dùng nó nội bộ mà không hề có ý định chuẩn hóa
    • Nếu CP/M dùng biến môi trường cho cấu hình, thì hẳn đã có sẵn một chuẩn cho việc dùng TMP hay TEMP, và DOS sẽ làm theo chuẩn đó
      Nhưng trở ngại thực sự là CP/M không có thư mục, và DOS 1.0 cũng vậy
    • Bạn có thể trích lại xem bạn đang nói đến câu nào không?
  • Khoảng năm 1995, Telstra, tức Australia Telecom, có chừng 50 nghìn máy desktop trên toàn tổ chức
    Một ngày nọ, trong thư mục home trên mạng của mọi người xuất hiện một tệp nhỏ tên null, có lẽ là vì một người dùng Unix đã thử viết file .bat
    Đó đúng là kiểu chuyện khiến người ta hỏi tại sao phải theo chuẩn có sẵn. Tôi đã định hỏi “tại sao phải chuẩn hóa”, nhưng nghĩ vậy có thể làm người Bắc Mỹ bối rối

    • Có lẽ ban đầu họ thử /dev/null rồi thất bại nên mới đổi thành null
      Nếu không thì bảo là do lập trình viên Unix làm nghe không hợp lý lắm. Có khi là lập trình viên DOS viết nhầm NUL thành null thì đúng hơn
    • Tôi tò mò không biết đoạn văn bản mà họ định vứt đi là gì
    • Một bộ cài driver của Logitech cũng từng làm chuyện tương tự
      Nó tìm một tệp tên NULL trên ổ cứng, và dĩ nhiên trong file .BAT có kiểu cú pháp như > NULL
  • Thành thật mà nói, với nhiều chương trình thì kiểu cấu hình vá của CP/M có khi còn tốt hơn cách rải dotfile khắp thư mục home

    • Nếu mọi người chỉ cần tuân thủ XDG Base Directory Specification thì chuyện file cấu hình bừa bộn sẽ không còn là vấn đề
      Ngày càng nhiều dự án áp dụng, kể cả những dự án từng cố chấp như Firefox
    • Một triết lý hơi đặc biệt bên phía suckless là các dự án của họ phần lớn được cấu hình bằng cách sửa mã nguồn rồi biên dịch lại
      Nếu nhìn theo kiểu mã nguồn mở hiện đại thì có thể xem là một cách tiếp cận tương tự. Chỉ là với chủ nghĩa khổ hạnh tổng thể đó, các dự án này có lẽ khá kén gu
    • Vốn dĩ mọi thứ nên nằm trong .config
      Vấn đề là nhiều lập trình viên ứng dụng nghĩ rằng riêng ứng dụng của họ thì đặc biệt và xứng đáng có thư mục riêng
    • Tôi vẫn thấy dotfile tốt hơn là cấu hình nằm rải rác trong một registry nhị phân trung tâm ở khắp nơi, vì còn có thể grep và quản lý bằng trình soạn thảo văn bản
      Có khi chỉ là vì tôi đã quen như vậy
    • Tôi ước gì chuyện này được chuẩn hóa. Nếu có bản phân phối nào đó có thể ép mọi thứ phải dùng thư mục .config thì với tôi đó là người thắng cuộc
      Dù vậy, có lẽ chúng ta đã lỡ thời điểm rồi
  • Tôi không ngờ chuyện này lại rối đến thế
    Bài học chắc là hãy luôn trỏ về cùng một đường dẫn, nếu không thì sẽ có chuyện lớn xảy ra

  • Tôi đã chỉ ra mấy chuyện khó chịu kiểu này của Microsoft suốt hàng chục năm
    Trước đây lúc nào cũng có một “senior developer” ở đó tỏ ra như biết hết mọi thứ và luôn có sẵn câu trả lời. Kiểu như “temp là temporary còn tmp là troubleshoot my pc, dành cho log debug. Thế nên tôi là senior còn anh thì không”
    Đến khi tôi thành senior hơn thì mới thấy việc đặt câu hỏi của mình là đúng, và giờ nếu nói chuyện với các lập trình viên Microsoft đời đầu thì họ giải thích rằng đó là lỗi nhưng được giữ lại vì tương thích ngược
    Nhưng rồi tôi lại tự hỏi tại sao lời biện hộ đó lại có giá trị, khi họ vin vào tương thích ngược nhưng vẫn thường xuyên đẩy ra những thay đổi phá vỡ tính tương thích cốt lõi và luồng công việc thực tế như New Outlook. Rồi họ rút lui bằng kiểu “tôi không phải lập trình viên tệ, anh cứ đi hỏi người mới ấy”
    Mà cũng chẳng thể hỏi người mới, vì họ ẩn sau rào cản tuyển chọn kiểu LeetCode. Thế nên việc các vấn đề thực tế như thế này không được sửa, còn những thứ như New Outlook lại xuất hiện, cũng chẳng có gì lạ. Mấy “senior developer” ngày xưa giờ đang làm ở đó, còn những lập trình viên thực thụ thì đã nghỉ hưu
    Ngay cả khi nhận được một câu trả lời có vẻ hợp lý từ Microsoft về việc các chương trình tùy tiện dùng thư mục Documents trong home của người dùng hoặc OneDrive vô tình xóa cưỡng bức nó, thì chỉ trong vòng 6 tháng Microsoft lại tung ra một thay đổi ngẫu nhiên làm hành vi tệ đi và phá hỏng chính lập luận cốt lõi đó
    Notepad cũng vậy. Trong các buổi phỏng vấn với lập trình viên, họ từng nói nó phải là một chương trình cực kỳ đơn giản vì rủi ro phải bằng 0, nhưng sau này lại gắn thêm đăng nhập tài khoản Microsoft và Copilot
    Tôi cho rằng kiểu thái độ lập trình viên theo LeetCode và văn hóa Microsoft đang phá hỏng cả ngành. Không thể có thảo luận bình tĩnh, vì mọi thứ trôi về kiểu “anh không làm ở Microsoft nên ý kiến của anh vô giá trị”
    Tôi vẫn nhớ rất rõ chuyện Google Chrome từng cài vào AppData để lách quyền quản trị. Rõ ràng mục đích ban đầu của tính năng đó không phải để bên thứ ba dùng nó cài đặt mà không cần quyền admin
    Nhưng vì lúc đó Chrome tốt thật, và người ta phải xử lý mớ hỗn loạn khi triển khai các ngoại lệ của bên thứ ba lên hàng triệu máy tính doanh nghiệp bị khóa, nên giờ các lập trình viên lại đóng gói nó như thể đó vốn là tính năng được thiết kế để làm vậy