300 likes | 454 Views
作業 1. 請寫一程式 , 該程式 ( 第一代行程 ) 會產生 a chain of process. 第一代行程印出 1, 第二代印出 2...... 第九代印出 9 及換列字元 ('<br>'). 第九代行程並產生九個兒子 , 每個兒子同樣印出自已的代碼 (a,b,c,d,e,f,g,h,i 等 ) 第九代行程等兒子們都結束後再印出換列字元並再印出 9 後結束 . 第八代再印出 8 後結束 ..... 以此類推 . 執行結果 : 123456789 XXXXXXXXX ( 次序未定 ) 987654321. 作業 2.
E N D
作業1 請寫一程式,該程式(第一代行程)會產生 a chain of process. 第一代行程印出1, 第二代印出2......第九代印出9及換列字元('\n'). 第九代行程並產生九個兒子, 每個兒子同樣印出自已的代碼(a,b,c,d,e,f,g,h,i 等) 第九代行程等兒子們都結束後再印出換列字元並再印出9後結束. 第八代再印出8後結束.....以此類推. 執行結果: 123456789 XXXXXXXXX (次序未定) 987654321
作業2 • 到老師的網頁上去下載作業2之資料檔(hw2datafiles.zip)放在自己的目錄(home directory)下. 資料檔內含5個文字檔(file1, file2, file3,....), 其中只有一個檔案含"unix"這個word. 寫一個程式, 此程式產生5個兒子, 每個兒子負責搜尋一個檔案(搜尋"unix"). 如果找到則在螢幕上印出 " PID=XXXX I found unix in filex" 否則印出 " PID=XXXX Search failure in filex" 父親等所有兒子結束後印出 "Thanks and good work, my son"
作業2.1 (1)將作業2 改為由指令列指定參數(command line arguments) 參數類型及意義如下: -p searchpattern -f filelist-to-be-seached exp: -f file1 file2 file3 file4 -ep environvar (註:由環境變數指定 search pattern) -ef environvar (註:由環境變數指定 一檔案名稱, 該檔案內部記錄 file list to be searchd) 參數-f 及 -ef 兩者只能出現一個 參數-p 及 -ep 兩者也只能出現一個 exp: a.out -p unix -f file1 file2 data1 data2 file3 a.out -p linux -ef filelist a.out -f file1 file2 file3 -ep searchpat (2)每個兒子及父親結束 之前要印出 cpu time used (直接套用program 2.11 exit handler之例子即可)
作業2.1 cont. • Child process會繼承parent之環境變數. 但如果child process呼叫execle() 或execve() (這兩個呼叫有傳遞新環境變數) 來執行新的程式, 則該child process是否還能讀取parent的環境變數? 請寫一程式測試之. • 一個process能否呼叫exec*()再來執行自己? 請寫一程式測試之.
作業3 (a) $mkdir foo $ln -s ../foo foo/testlink (b) $mkdir foo $ln -s foo foo/testlink 請測試上述之指令 (a)處之testlink link到那裡? (b)處之 ln 指令是錯誤的. 為什麼?
作業3 cont. #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { printf("**********************************"); /* 1 */ if (execlp("echo", "echo", "good morning", NULL) < 0) { perror("The exec of command failed"); exit(1); } printf("#########################"); /* 2 */ } 請問此程式執行後1 處之星號會不會列印出來? 為什麼? 2處之# 會不會列印出來?
作業3 cont. #include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <sys/wait.h> /* sem-test.c*/ int prnt(int i) { int j; for(j=0; j<2000; j++) { if (j % 40 == 0) fprintf(stderr,"\n"); fprintf(stderr,"%d",i); } }
作業3 cont. int main() { int i; pid_t childpid; int status; for (i=1; i<10; i++) if (!fork()) { prnt(i); exit (0); } while(childpid = wait(&status)) if ((childpid == -1) && (errno != EINTR)) break; }
作業3 cont. 上述程式中之9個child process 會競爭使用terminal這個shared resource, 因此輸出(列印到螢幕)並無一定之次序 (此乃O.S 之critical section problem). 請用pipe這個tool來模擬製作 semaphore 變數以俾達成9個child process 間之同步(synchronization, 即壹個process全部輸出完畢後另壹個process才可以使用termina來輸出). 請寫參個函式: int sem_init(int s[]); int p(int s[]); (令稱wait(s);) int v(int s[]); (令稱signal(s);) 並在主函式中適當的地方呼叫此參個函式來達成child process 間之同步.
作業4 寫一程式. 該程式會create兩個pipe(pipe1及pipe2))及兩個兒子. 該程式從stdin讀取user之輸入, 輸入格式如下: 1xxxxxxxxxxxx 1xxxxxxxxxxxxxxxxx 2xxxxxxxxx 2xxxxxxxxxxxxxx 1xxxxxxxxxx .................. ....................... 每列第一個字為字元1,2或其它任何字元.其它任何字元代表輸入結束.該程式將"1"列的文字(不包含"1")依序寫入pipe1,由兒子1依序讀取, 將"2"列的文字依序寫入pipe2,由兒子2依序讀取. 程式若讀到某列之首字為其它任何字元的話則將'\001'字元分別寫入pipe1及pipe2(代表結束字元)並且等待兩個兒子結束. 當兒子讀到結束字元則結束讀取並將讀取之文字寫到磁碟檔中並結束. (兩個兒子各create一個檔案分別叫text1及text2). 該程式等兩個兒子結束後exec cat 指令將text1及text2顯示於螢幕上.
作業2.2 • 將作業2 修改為: 到老師的網頁上去下載作業2之資料檔放在自己的目錄(home directory)下. 資料檔內含5個文字檔(file1, file2, file3,....). 寫一個程式, 此程式產生5個兒子, 每個兒子負責搜尋一個檔案(搜尋"unix").兒子如果找到則在螢幕上印出"pid=xxxx, I found unix in filex" 並送出SIGUSR1 signal 給所有家族成員後結束. 父親收到signal後印出"Good work, my son"並結束. 其他成員收到signal後則印出自己的pid並結束搜尋.(如果兒子還未收到signal之前就已經搜尋完畢則關閉檔案並結束.有可能5個檔案中均未含"unix", 因此父親仍必須wait 5個兒子結束)
作業5 發展壹個client-server程式. Server首先create壹個well-known FIFO(建立於 /tmp 目錄下, 檔名為s學號(例:s90160116),並open for read/write) 來接受clients之requests. Request 結構中包含了client process之PID, service number,及optional data. Server每讀取壹個Request隨即產生壹個兒子(slave)來處理該Request(此種作法稱為concurrent server). Slave根據client之PID來建立各別的client-specific FIFO(建立於 /tmp 目錄下,並open for read/write, 檔名為serv.PID, 例:serv.25795)並將client所要求服務之reply 寫入client-specific FIFO 中由client讀取. Server所模擬之服務(service number)暫定如下: 1: 今日溫度報告 目前股市大盤點數報告 即時新聞報告 2: 檔案閱讀 (optional data為欲閱讀檔案名稱) 3: 猜數字遊戲(see 作業option 2, server及client間之protocol自己訂定) (Client 和end user間之介面自己訂定)
作業5 cont. Server每隔三分鐘(利用alarm()設定)去讀取資料檔 (newdata, 用wordpad編輯資料檔)來更新今日溫度報告, 目前股市大盤報告及即時新聞報告並放置於一global buffer中. 例:(資料檔及印出之格式) 今日溫度: 台北 23降至17~°c 台中 20~27°c 高雄 22~27°c 台東 22~26°c 目前股市大盤點數: 5876, +36 即時新聞: 春節包機 增北京一地 假面男控江姐涉非常光碟 101鐵片砸傷人 停工停業 購物中心停業1天 全台狂飲薄酒萊 法國人傻眼 今年失業率可望低於5% 中油台塑明起調漲瓦斯價格
server (background process) fork fork slave slave write reply write reply read request client-specifit FIFO client-specifit FIFO well-known FIFO write request write request read reply read reply client client
作業6 • 寫一程式作矩陣相乘. 該程式從標準輸入設備(stdin)讀取兩個5x5矩陣,產生一個pipe,再fork 5個兒子. 第一個兒子負責產生乘積矩陣之第一列結果,並將結果透過pipe傳給父親. 第二個兒子負責產生第二列乘積並將結果透過pipe傳給父親. 第三個兒子依此類推...... 父親最後將整個乘積矩陣列印在螢幕上.
作業7 1.將作業2(檔案搜尋)改成multithreaded版本. 2.將作業6(矩陣相乘)改成multithreaded版本. 寫一程式, 該程式從stdin讀取兩個5x5矩陣並且create 5個thread. 每個thread負責產生乘積矩陣之一列結果.(main thread和5個thread不必使用pipe傳輸資料, 直接使用global variable/shared memory) Main thread最後將乘積矩陣列印在螢幕上. 使用gcc 翻譯程式時必須加上參數-lthread. 例: gcc -lthread programname
optional 1 寫一程式. 該程式含下列函式 int wordlength(); 傳回值為: running machine上整數 (int)之length (in bit) (註:不能使用sizeof ) int rightrot(int n, int b); 傳回值為: 將參數 n 向右旋轉b個bits後之值 int invert(int n, int p, int b); 傳回值為: 將參數 n 由 bit position p 開始連續invert b個 bits後之值( bit position由 右邊最低位元 0 起算) 程式要求: rightrot()及 invert()兩個函式必須只用一條statement完成 EXP: int rightrot(int n, int b) { return(............................); }
optional 1 cont. 寫一程式. 該程式從標準輸入接受user 的輸入. User每次輸入一列文字(一列文字以enter 鍵結尾, 文字最長為255字). 該程式接受一列文字之後馬上印出該列文字的反轉字串. (必須寫一函式reverse()來傳回反轉字串) int reverse( char * s); User在一列開頭按下ctrl-D(EOF) 結束輸入及程式執行. 例: abcdefg (user輸入) gfedcba (程式輸出) wertyhjkl (user輸入) lkjhytrew (程式輸出)
optional 2 寫一個猜數字遊戲程式. 該程式執行時會隨機產生4個0-9之不重覆數字並要求user輸入他的guess.(user從鍵盤輸入4個0-9之不重覆數字). 如果user所猜的數字對且位置也對, 則程式回應a,.如果數字對但位置不對, 則程式回應b. 例: (程式所產生的隨機數字為5910) your guess? 5031(程式要求user猜4個0-9之不重覆數字, user輸入5031) 1a2b (程式回應) your guess? 2749 0a1b (程式回應) your guess? 5190 2a2b (程式回應) your guess? 5910 Congratulation, number of guess: 4 Once more (y/n)? y your guess ?
Optional 3 1 2 3 11 2 3 22 1 2 33 3 1 寫壹個數字配對程式. 數字配對之規則如右表: (a.) 如給予下列兩組數字組合(1.和 2), 總共能 配出多少組不同之數字組合? 1. 111222333 2. 123123123 111111111 (1.和 1.配) 123212331 (1.和 2.配) 123213321 (2.和 1.配) 123121113 (4.和 1.配) 111223323 (2.和 4.配) 23 2 33 1 4.
Optional 3 cont. (b.)如給予下列三組數字組合,總共能配出多少組 不同之數字組合?(要將所有組合列印出來) 1. 111223323321313 2. 123132123122131 3. 132311223212113
Reading Assignment • UNIX完全參考指南翁仲岳編著,文魁 第1,2章 第6,7章 第8,9章 第14章 第15,16章 第20,21,22章 補充講義18, 19, 21章
Shared memory (program1) /* Run this program first in the background */ #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <fcntl.h> #define SHM_KEY ((key_t)99887) #define PERM (SHM_R | SHM_W) #define SHM_SIZE 4
shared memory (program1 cont.) int main() { int *shmptr; int shmid; int i; shmid=shmget(SHM_KEY, SHM_SIZE, PERM | IPC_CREAT); shmptr=(int *)shmat(shmid, (char *)0, 0); *shmptr=0; printf("##111## %d\n", *shmptr); while( *shmptr < 1); /* wait for program 2 */ for(i=0; i<8000000; i++) (*shmptr)++; printf("##111## %d\n", *shmptr); shmdt( (void *)shmptr); shmctl(shmid, IPC_RMID, NULL); }
Shared memory (program2) /* After running program1 in the background, run this program */ #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <fcntl.h> #define SHM_KEY ((key_t)99887) #define PERM (SHM_R | SHM_W) #define SHM_SIZE 4
Shared memory (program2 cont.) int main() { int *shmptr; int shmid; int i; shmid=shmget(SHM_KEY, SHM_SIZE, PERM | IPC_CREAT); shmptr=(int *)shmat(shmid, (char *)0, 0); printf("**222** %d\n", *shmptr); for(i=0; i<8000000; i++) (*shmptr)++; printf("**222** %d\n", *shmptr); for(;;); shmdt( (void *)shmptr); shmctl(shmid, IPC_RMID, NULL); }
POSIX 1.b semaphore (P1) #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <fcntl.h> #include <synch.h> #include <semaphore.h> #include <stdlib.h> #include <sys/stat.h> #define SHM_KEY ((key_t)99887) #define PERM (SHM_R | SHM_W) #define SHM_SIZE 4 int main() { int *shmptr; int shmid; int i; sem_t *sem;
POSIX 1.b semaphore (P1 cont.) sem= sem_open("/tmp/mylock", O_CREAT, S_IRWXU, 1); shmid=shmget(SHM_KEY, SHM_SIZE, PERM | IPC_CREAT); shmptr=(int *)shmat(shmid, (char *)0, 0); *shmptr=0; printf("##111##%d\n", *shmptr); while( *shmptr < 1); for(i=0; i<8000000; i++) { if (sem_wait(sem) == -1) { perror("Semaphore invalid"); exit(1); } /* critical section */ (*shmptr)++; /* end of critical section */ if (sem_post(sem) == -1) { perror("Semaphore done"); exit(1); } } printf("##111##%d\n", *shmptr); shmdt( (void *)shmptr); shmctl(shmid, IPC_RMID, NULL); }
POSIX 1.b semaphore (P2) #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <fcntl.h> #include <stdlib.h> #include <sys/stat.h> #include <semaphore.h> #define SHM_KEY ((key_t)99887) #define PERM (SHM_R | SHM_W) #define SHM_SIZE 4 int main() { int *shmptr; int shmid; int i; sem_t *sem;
POSIX 1.b semaphore (P2 cont) sem= sem_open("/tmp/mylock", 0); shmid=shmget(SHM_KEY, SHM_SIZE, PERM | IPC_CREAT); shmptr=(int *)shmat(shmid, (char *)0, 0); printf("**222** %d\n", *shmptr); for(i=0; i<8000000; i++) { if (sem_wait(sem) == -1) { perror("Semaphore invalid"); exit(1); } /*******critical section*********/ (*shmptr)++; /********end of critical section********/ if (sem_post(sem) == -1) { perror("Semaphore done"); exit(1); } } printf("**222** %d\n", *shmptr); shmdt( (void *)shmptr); shmctl(shmid, IPC_RMID, NULL); }