Stories

Detail Return Return

”新建文件”只是早期Unix上touch命令的副作用?程序別掛掉就行 - Stories Detail

在西斯廷教堂的天頂上,米開朗基羅留下了人類藝術史上最具張力的名作——《創造亞當》。畫面中,上帝在天使的簇擁中俯身而下,手指即將觸碰到大地之上的亞當。這一指尖交會的瞬間,凝結了“以神之手創造人類”的想象,也象徵着生命、自由意志、甚至靈魂的誕生

看到這幅畫的時候,我腦中突然冒出一個念頭:*nix系統裏的touch命令,會不會也是受此啓發?在操作系統的世界裏,用户就是數字造物主,只需手指一點,“touch”一下,文件便無中生有,頗有幾分神性。

直到有一天,在翻閲了早期Unix系統上touch命令的源碼之後,才發現這個命令最初的設計目的,其實只是單純地修改文件的最後修改時間。至於“新建文件”,那隻不過是一個順帶發生的副作用,甚至可以説是一種不得已而為之的行為。

今天,我們就來聊聊早期Unix系統中touch命令的實現方式,看看這個樸素的命令是如何在陰差陽錯中,被誤解為“神之觸碰”的。

Unix V7中的touch.c

touch命令的最初版本可以追溯到1979年發佈的Unix第7版。那時,它還只是一個不到100行的小程序。在當年的手冊頁裏,touch命令被簡潔地描述為:“update date last modified of a file”——即修改文件的最後變更時間

有趣的是,源碼touch.c裏採用了一種頗為“狡猾”的技巧:通過假裝修改文件內容,來“欺騙”系統更新時間戳。具體做法如這幾行代碼所示:

char junk[1];
int fd;

...

if( read(fd, junk, 1) < 1)
    {
    close(fd);
    goto bad;
    }
lseek(fd, 0L, 0);
if( write(fd, junk, 1) < 1 )
    {
    close(fd);
    goto bad;
    }
close(fd);

bad:
    fprintf(stderr, "Cannot touch %s\n", name);
    return;

這裏先讀取了1個字節,然後立刻原樣寫回這個字節。相當於,選中——Ctrl+C——保持選中Ctrl+V。這樣一來,在文件內容不變的前提下,就間接地更新了文件的最後修改時間

乍一看,這種“偽修改”的方法相當機智,但也有個明顯的問題:要想成功讀取並寫回1個字節,文件首先必須存在,其次還得至少有1個字節的內容。換句話説,空文件根本不存在的文件就像現代編程語言中的null——必須特殊對待,一旦處理不當,就會導致程序出錯甚至崩潰。

touch的作者顯然也意識到了尷尬的“null“。於是,他們加了一個簡單粗暴的補丁:文件不存在?那就新建一個唄。文件是空的?那就再重新創建一遍唄。問題迎刃而解!

就這樣,原本只想“更新時間”的命令,順帶就擁有了新建文件的能力。這完全是出於工程上的權宜之計——既非神啓,也非致敬米開朗基羅。創造這個動作,在這裏只是為了讓程序別掛掉而已。

至於新建文件的實現方式,就藏在touch.c最後的幾行代碼中,而那幾行,也有一個小小的故事。

拼寫錯誤的creat

新建文件的代碼如下所示:

create:
    if( (fd = creat(name, 0666)) < 0)
        goto bad;
    close(fd);

從這幾行源代碼可以看出,touch是通過調用一個名為creat的函數(系統調用)來新建文件的。引人注目的是,這個creat少了末尾的字母“e”,而在上方作為標籤的create:卻是拼寫正確的。

是貝爾實驗室的理工男文科太差,連單詞都拼寫錯了?還是這是一種程序員式的極簡主義——為了少敲一個鍵,乾脆把單詞縮寫了?又或者,是受限於當年計算資源的緊張,不得不節省每一個字符?

總之,為什麼把“create”寫成“creat”,這個問題多年來始終為程序員們津津樂道。各種猜測和玩笑層出不窮,直到有一次,Unix的共同締造者之一Ken Thompson在採訪中被問到,“如果你能重新設計UNIX,會改些什麼?”。

Ken幽默地回答説:“我會把creat拼成帶e的create”。


説起來,用touch作為修改文件時間的命令,其實還挺貼切的。畢竟,如果你沒“碰”這個文件,當然“毫無變化”,自然也不該更新它的時間戳;但如果碰了,那就像留下了“最新的指紋”一樣,時間戳也就隨之更新。

順帶一提,把touch理解成“觸碰”既能表達輕微的變更,又點出了後果——文件狀態發生變化。但如果理解成“摸一把”來創建文件、更新時間,那就不太妙了……因為「痴漢は犯罪!」。

🔚

user avatar wujingquan Avatar skyselang Avatar mianlengxincidehongjiu Avatar rivers_chaitin Avatar rui_sen Avatar seth9shi Avatar phpercode Avatar easynvr Avatar niandb Avatar huanledeyanjing Avatar guaguokedeputaojiu Avatar jkdataapi Avatar
Favorites 15 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.