# 系統程式筆試考古題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://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. 中正作業系統實驗室,及所開設的課程屬於哪一個門派?
>明教