1. 程式人生 > 資訊 >小米筆記本 Pro X 現身小米有品,將於 6 月 1 日開售

小米筆記本 Pro X 現身小米有品,將於 6 月 1 日開售

專案內容
這個作業屬於哪個課程 <班級課程的主頁連結>
這個作業的要求在哪裡 <作業要求連結接地址>
學號-姓名 18043213-丁宇航
作業學習目標

瞭解程序間通訊的常用方式;

掌握管道、訊息佇列、訊號量、共享記憶體實現程序間通訊的方法。

1. 舉例說明使用匿名管道進行程序通訊。

當程序使用 pipe 函式,就可以開啟位於核心中的這個特殊“檔案”。同時 pipe 函式會返回兩個描述符,一個用於讀,一個 用於寫。如果你使用 fstat 函式來測試該描述符,可以發現此檔案型別為FIFO 。而無名管道的無名,指的就是這個虛幻 的“檔案”,它沒有名字。 man 2 pipe 父程序 fork 出一個子程序,通過無名管道向子程序傳送字元,子程序收到資料後將字串中的小寫字元轉換成大寫並輸出。

2. 舉例說明使用mkfifo

命令建立命名管道以及簡單演示管道如何工作。

使用 mkfifo 建立 hello 檔案後,檢視檔案資訊如下: 使用 cat 命令列印 hello 檔案內容,cat 命令被阻塞住。 開啟另一個終端,執行: 被阻塞的 cat 又繼續執行完畢,在螢幕列印 “hello world” 。

3. 編寫兩個程式使用第2題中建立的管道進行通訊。

分別開啟兩個終端,分別執行 pipesend 和 piperecv : 現在兩個終端都處於阻塞狀態,我們在執行 pipe_send 的終端輸入資料,然後我們就可以在執行 pipe_recv 的終端看到相應的輸出:

4. 編寫兩個程式分別通過指定的鍵值建立IPC

核心物件,以及獲取該指定鍵值的IPC核心物件。

程式 ipccreate 用於在指定的鍵值上建立 ipc 核心物件。./ipccreate 0 0x8888 表示在鍵值 0x8888 上建立共享記憶體。 程式 ipcget 用於在指定的鍵值上獲取 ipc 核心物件的 id 號。./ipcget 0 0x8888 表示獲取鍵值 0x8888 上的共享記憶體 id 號。

5. 編寫一個程式可以用來建立、刪除核心物件,也可以掛接、解除安裝共享記憶體,還可以列印、設定核心物件資訊。

./shmctl -c : 建立核心物件。 ./shmctl -d : 刪除核心物件。 ./shmctl -v : 顯示核心物件資訊。 ./shmctl -s : 設定核心物件(將許可權設定為 0600 )。 ./shmctl -a : 掛接和解除安裝共享記憶體(掛接 5 秒後,再執行 shmdt ,然後退出)。
 shmctl.c 

#include 
<unistd.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdio.h> #include <time.h> #include <stdlib.h> #include <string.h> #define ASSERT(res) if((res)<0){perror(__FUNCTION__);exit(-1);} // 列印 ipc_perm void printPerm(struct ipc_perm *perm) { printf("euid of owner = %d\n", perm->uid); printf("egid of owner = %d\n", perm->gid); printf("euid of creator = %d\n", perm->cuid); printf("egid of creator = %d\n", perm->cgid); printf("mode = 0%o\n", perm->mode); } // 列印 ipc 核心物件資訊 void printShmid(struct shmid_ds *shmid) { printPerm(&shmid->shm_perm); printf("segment size = %ld\n", shmid->shm_segsz); printf("last attach time = %s", ctime(&shmid->shm_atime)); printf("last detach time = %s", ctime(&shmid->shm_dtime)); printf("last change time = %s", ctime(&shmid->shm_ctime)); printf("pid of creator = %d\n", shmid->shm_cpid); printf("pid of last shmat/shmdt = %d\n", shmid->shm_lpid); printf("No. of current attaches = %ld\n", shmid->shm_nattch); } // 建立 ipc 核心物件 void create() { int id = shmget(0x8888, 123, IPC_CREAT | IPC_EXCL | 0664); printf("create %d\n", id); ASSERT(id); } // IPC_STAT 命令使用,用來獲取 ipc 核心物件資訊 void show() { int id = shmget(0x8888, 0, 0); ASSERT(id); struct shmid_ds shmid; ASSERT(shmctl(id, IPC_STAT, &shmid)); printShmid(&shmid); } // IPC_SET 命令使用,用來設定 ipc 核心物件資訊 void set() { int id = shmget(0x8888, 123, IPC_CREAT | 0664); ASSERT(id); struct shmid_ds shmid; ASSERT(shmctl(id, IPC_STAT, &shmid)); shmid.shm_perm.mode = 0600; ASSERT(shmctl(id, IPC_SET, &shmid)); printf("set %d\n", id); } // IPC_RMID 命令使用,用來刪除 ipc 核心物件 void rm() { int id = shmget(0x8888, 123, IPC_CREAT | 0664); ASSERT(id); ASSERT(shmctl(id, IPC_RMID, NULL)); printf("remove %d\n", id); } // 掛接和解除安裝 void at_dt() { int id = shmget(0x8888, 123, IPC_CREAT | 0664); ASSERT(id); char *buf = shmat(id, NULL, 0); if (buf == (char*)-1) ASSERT(-1); printf("shmat %p\n", buf); sleep(5); // 等待 5 秒後,執行 shmdt ASSERT(shmdt(buf)); printf("shmdt %p\n", buf); } int main(int argc, char *argv[]) { if (argc < 2) { printf("usage: %s <option -c -v -s -d -a>\n", argv[0]); return -1; } printf("I'm %d\n", getpid()); if (!strcmp(argv[1], "-c")) { create(); } else if (!strcmp(argv[1], "-v")) { show(); } else if (!strcmp(argv[1], "-s")) { set(); } else if (!strcmp(argv[1], "-d")) { rm(); } else if (!strcmp(argv[1], "-a")) { at_dt(); } return 0; }
先在另一個終端執行 ./shmctl -a ,然後在當前終端執行 ./shmctl -v

6. 編寫兩程式分別用於向訊息佇列傳送資料和接收資料。

msg_send程式定義了一個結構體Msg,訊息正文部分是結構體Person。該程式向訊息佇列傳送了10條訊息。

先執行 ./msg_send ,再執行 ./msg_recv 。 接收所有訊息: 接收型別為 4 的訊息,這時要重新執行 ./msg_send : 接收型別小於等於 3 的所有訊息,這是不用再執行 ./msg_send : 還有一個函式來操作訊息佇列核心物件的 man 2 msgctl

7. 編寫程式舉例說明訊號量如何操作。

設定和獲取訊號量值的函式 semctl : man 2 semctl 請求和釋放訊號量 semop man 2 semop 訊號量操作

8. 編寫程式使用訊號量實現父子程序之間的同步,防止父子程序搶奪CPU

字元是成對出現的,如果修改程式把74行 sem_p(); 和81行 sem_v(); 註釋掉,在編譯執行會發現字元可能就不會成對出現了,這裡就是用訊號量來實現程序間的同步的。