# 系統程式筆試考古題2018 ###### tags: `考古題` 1. 請簡單比較一下傳統Linux的權限控制及ACL(使用getfacl和setfacl)的權限控制,舉一個例子說明傳統Linux的權限控制做不到,而ACL做得到 >ACL:access control list setfacl提供更細部的權限控制,而某些情況傳統Linux的權限控制是不足的。 因為傳統Linux指提供三種權限:usr, grp, others。如果今天要開放四種不同的權限(使用者、校友、老師、在校生),就一定得使用ACL。 ```c= //授予myuser使用者rx權限 setfacl -m u:myuser:rx myfile.txt ``` 參考影片: https://www.youtube.com/watch?v=fPBzoDszDh8 2. 請問如何用google查詢到監測檔案系統的函數名稱(hint:要下哪些關鍵字) >"linux c inotify function" ```c= //持續監看tmp目錄下的所有檔案事件 inotifywait -m /tmp //對檔案做一些操作 date > /tmp/date.output rm /tmp/date.output ``` 這時候就會看到 inotifywait 的輸出中出現以下的檔案事件訊息: /tmp/ CREATE date.output /tmp/ OPEN date.output /tmp/ MODIFY date.output /tmp/ CLOSE_WRITE,CLOSE date.output /tmp/ DELETE date.output 參考影片: https://www.youtube.com/watch?v=F0Jk8AAWwv8&ab_channel=ShiwuLo 3. 目前在Linux系統中只有「一個」行程(該行程為prog)是活躍的狀態(active,換句話說就是需要CPU),其他行程都是inactive的狀態(目前不需要CPU)。請問下列這些指令會讓這個行程的執行時間造成什麼樣的影響(hint: nice -n -5是提高此行程對其他行程的優先權,nice -n 5是降低此行程對其他行程的優先權) sudo nice -n -5 prog sudo nice -n 5 prog >毫無影響。nice是用於需要CPU的process之間互相搶奪,才有作用。 因為只有一個active process,所以沒有影響。 4. 請問下列程式的執行結果,解釋你的答案 ```c= printf(“Hello ”); fork(); printf(“Ron\n”); ``` >將會印出: helloRon <= parent helloRon <== child 因為printf預設是line buffered,所以hello會被存在buffer,fork完之後,child和parent在buffer都有hello,所以會印出來兩次。 5. 請描述如何同時對parent和child除錯 Hint<attach ,set waiting = 0 ,while loop> >gdb預設是對parent除錯,可使用set follow-fork-mode child切換為對child除錯。 >![](https://i.imgur.com/JhFKaSU.png) https://ephrain.net/gdb-%E4%BD%BF%E7%94%A8-gdb-%E9%99%A4%E9%8C%AF-fork-%E5%87%BA%E4%BE%86%E7%9A%84%E5%AD%90%E9%80%B2%E7%A8%8B/ https://visualgdb.com/gdbreference/commands/set_follow-fork-mode 6. 請問何謂殭屍行程 >child已經結束,而**parent沒有回收child在process table裡的entry**,造成資源的浪費。 7. System()和execv()都可以執行外部程式,請問下列程式碼會在螢幕上印出多少個"fork"? ```c= int main(int argc, char* argv[]){ system("ls"); fork(); fork(); printf("fork\n"); return 0; } ``` >fork兩次,會印出四次”fork”。 ```c= int main(int argc,char* argv[]){ char* const para_list[] = {"/bin/ls","-l",NULL}; execv("/bin/ls",para_list); fork(); fork(); printf("fork\n"); return 0; } ``` >0次,因為exec家族的函數會把整個process換掉,之後的函式都沒有效用。 >實際上,system()是靠著fork、wait和exec(“sh”, “ -c”, cmd)實做出來的。 8. 請問可以使用signal函數攔截ctr-c這組按鍵輸入嗎? > 可以,使用signal(SIGINT, sig_handler); 9. Linux中signal編號1-31,與編號SIGRTMIN~SIGRTMAX這兩個族群有什麼不同? Hint<如果連續、大量的發送signal各會發生什麼事情> >前面32個是不可靠訊號,後面的是可靠訊號。 不可靠訊號指的是發送的次數和接受次數常常不同,比如:在sighandler之中,sleep(),然後連續按十次ctrl+c。可能只會收到第一次ctrl+c。 可靠的訊號雖然稱為可靠,只要送訊號的速度快到OS kernel無法負荷,也不是那麼可靠。 10. 程式碼如下:在上一回合的執行當中,程式執行到C函數。在這一回合的執行中,程式碼執行到B函數的時候可以使用longjmp到C函數嗎?(提示:想一下堆疊的狀態) ```c= sigjmp_buf jmp_buf_a, jmp_buf_b; A() { setjump(&jmp_buf_a); B(); } B() { if(XXX) longjmp(&jmp_buf, 1); C(); } C() { setjmp(&jmp_buf_c);} ``` >可以,上一回合執行C(),**已經設定好SP、PC、R0~R31**,在B()之中,可以透過longjmp指令跳回C()。 11. 請解釋dup這個函數的用途,請說明下列程式碼中printf(“hello\n”)會將資料寫到哪個地方(pipe?螢幕?) ```c= pipe(pipefd); ret = fork(); if (ret==0) { /*child*/ close(1); dup(pipefd[1]); close(pipefd[1]); close(pipefd[0]); printf("hello\n"); } else { /*...*/} ``` >將一個無人使用的file descriptor,指向dup參數中的fd所指向的file table。以上方程式為例,將1號fd關閉,然後將1號指向pipefd[1]所指向的file table。 printf會寫到pipe之中,因為stdout已經被重新指向了。 12. 請問pipe可否「繼承」給子行程,如果沒有特殊的設定,請問執行execve-like的系統呼叫以後,pipe可否繼承給新載入的程式碼(提示:在Linux內可以打像下列這樣的指令:$ ls -R / | sort,bash如何達成這樣的指令呢?) >子行程可以繼承pipe。在exec之前將stdout導向到pipe,可以在exec之後存取pipe。 比如:$ ls -R / | sort, 第一個process(ls)會將stdout指向pipefd[1],然後執行exec(“ls”); 接著第二個process(sort)會把stdin導向到pipfd[0],才執行exec(“sort”)。 13. mutex在大部分的情況都比semaphore快,請提出一個例子,說明非使用semaphore不可。 >semaphore只要一去等待,就會context switch,而context switch是有overhead(大約10,000個cycle),要是critical section的程式很短,用semaphore就很不划算。 >但是在多個thread想進入critical section,要sem_wait的時候,**寧願context switch也不要一直跑while loop**,佔用CPU資源。 >**參考影片**: >https://www.youtube.com/watch?v=-OLyMcH2jqc 14. 請說明adaptive mutex在鎖定時的機制。(提示:假設p嘗試進入critical section,而q已經在critical section內了。這時候如果1.) p, q在同一個core會怎樣,如果2.) q正在waiting會怎樣,如果3.) q不在waiting會怎樣,分別針對前述三個狀況,回答sleep或spinlock(即,busy waiting)) >sleep指的就是ctx-switch >1. p, q在同一個core:p進入sleep狀態 >2. q正在waiting:p進入sleep狀態(因為q沒有進度,p不可能等到) >3. q不在waiting :p會busy waiting(因為q正在跑,p猜他快等到了) https://www.youtube.com/watch?v=-OLyMcH2jqc&t=1293s 15. 宣告全域變數前,如果加上 “_ _thread” 這個關鍵字,那麼編譯器會怎樣處理各個thread對該全域變數的存取?(提示:32位元會使用gs暫存器,64位元會用fs暫存器,然後對變數...) >變數會變成thread local storage,也就是每一個thread都擁有一份自己的變數。 16. 請問下列二種id在使用上的差別 ```c= ptid = pthread_create(...); tid = gettid() int gettid() { return syscall(SYS_gettid);} ``` >那兩種id?看不懂題目 >gettid = get thread id >因為libc沒有實做這個system call,所以只能自定義一個函式。 17. 下列何者最能描述授課老師對於同學們的最高期許 >乾坤大挪移 18. 中正作業系統實驗室,及所開設的課程屬於哪一個門派? >明教