第五章《Terminals》和第六章《Managing Text-Based Screens with curses》意義不大,所以只挑揀了一個(gè)典型用例,和同樣內(nèi)容不太多的第七章《數(shù)據(jù)管理》(略去不常用的 dbm 數(shù)據(jù)庫)放在一起。順便把標(biāo)題也改了,畢竟這本書只算入門級(jí)的嘛,看完后要學(xué)的東西還很多的。
termios 結(jié)構(gòu)體
通過與該結(jié)構(gòu)體相關(guān)的函數(shù),例如 int tcgetattr(int fd, struct termios* termios_p)
和 int tcsetattr(int fd, int actions, const struct termios* termios_p)
,可以改變終端的輸入和輸出行為。該結(jié)構(gòu)體里面有不少五花八門的咚咚,頭都給我看花了,而且很多玩意兒感覺也沒什么用——都 21 世紀(jì)了,還在純字符界面里玩花哨,誰鳥你?去其糟粕之后,也許下面這段控制是否回顯輸入的代碼算是真正有用的功能之一,可用于提示用戶輸入密碼:
struct termios oldTermios;
struct termios newTermios;
int infd = fileno(stdin);
tcgetattr(infd, &oldTermios);
newTermios = oldTermios; // 創(chuàng)建副本,便于用完后恢復(fù)初始設(shè)置。
printf("Input password: ");
newTermios.c_lflag &= ~ECHO;
tcsetattr(infd, TCSAFLUSH, &newTermios); // 禁用輸入回顯。
char* password = NULL;
size_t n = 0;
getline(&password, &n, stdin); // 屏幕上應(yīng)當(dāng)看不到輸入的字符。
tcsetattr(infd, TCSANOW, &oldTermios); // 恢復(fù)初始設(shè)置。
printf("\nYour password is \"%s\".\n", password); // 輸出剛才“盲打”的內(nèi)容。
free(password);
管理內(nèi)存
void* malloc(size_t size)
、void* calloc(size_t number_of_elements, size_t element_size)
、void* realloc(void* existing_memory, size_t new_size)
和 void free(void* ptr_to_memory)
已經(jīng)風(fēng)騷二十多年了,沒什么特別的,除了下面這種初學(xué)者易犯的錯(cuò)誤:
p = realloc(p, size * 2); // 假設(shè)前面沒有創(chuàng)建 p 的副本。
realloc
在成功時(shí)返回新內(nèi)存的地址,老內(nèi)存被自動(dòng)釋放;失敗返回 NULL
,老內(nèi)存不變!也就是說,如果這句代碼失敗,p
就成了一個(gè)空指針,而原先的內(nèi)存已經(jīng)無法追蹤,從而導(dǎo)致內(nèi)存泄露!
文件鎖
《BLP》講了三種方式,用起來都非常簡(jiǎn)單:
- 使用函數(shù)
int open(const char* path, int oflags, mode_t mode)
,并帶上 O_CREAT
和 O_EXCL
標(biāo)識(shí),來創(chuàng)建鎖文件。
- 使用函數(shù)
int fcntl(int fildes, int command, struct flock* flock_structure)
對(duì)文件進(jìn)行局部鎖定。
- 使用函數(shù)
int lockf(int fildes, int function, off_t size_to_lock)
對(duì)文件進(jìn)行局部鎖定。
這三種方式創(chuàng)建的鎖都屬于“勸告鎖”(Advisory Lock)。勸告鎖僅僅是進(jìn)程間的一種“游戲規(guī)則”,所以只對(duì)按規(guī)則出牌的進(jìn)程起作用。如果有進(jìn)程不按規(guī)矩辦事,通過其他方式直接操作被“鎖住”的文件,內(nèi)核并不會(huì)阻止。勸告鎖需要多個(gè)進(jìn)程的協(xié)作才能生效;在同一個(gè)進(jìn)程中,即使在前面加了鎖,后面的代碼也無法檢測(cè)出來,加鎖操作總是會(huì)成功。勸告鎖很有畫地為牢的感覺……
要想徹底鎖住文件,必須使用“強(qiáng)制鎖”(Mandatory Lock),《BLP》沒有講。上網(wǎng)搜了一下,步驟是:
- 使用
-o mand
選項(xiàng)掛載文件系統(tǒng)。強(qiáng)制鎖必須要得到文件系統(tǒng)支持才能生效。
- 修改要加鎖的文件的權(quán)限:設(shè)置 SGID 位,并清除組可執(zhí)行位。
- 使用
fcntl
對(duì)文件進(jìn)行加鎖或解鎖,步驟和勸告鎖相同。
強(qiáng)制鎖不是 POSIX 兼容的,而且由于 Linux 無法解決某些競(jìng)爭(zhēng)條件,使得它不可靠。詳見 Linux 內(nèi)核文檔“mandatory-locking.txt”,注意其中的第 0 個(gè)問答就是“Why you should avoid mandatory locking”。