作業系統第二次上機實驗-程式通訊

pppNut發表於2020-11-05

實驗題目:程式通訊

實驗目的

  1. 熟練使用 Linux 的 C 語言開發環境
  2. 掌握 Linux 作業系統下的併發程式間同步
  3. 掌握 Linux 作業系統下的程式間通訊

實驗內容

  1. 瞭解常見的訊息通訊方式:訊號機制、訊息佇列機制、共享記憶體機制和管道機制。
  2. 掌握訊息佇列機制中常用的系統呼叫有:建立一個訊息佇列 msgget; 向訊息佇列傳送
    訊息 msgsnd;從訊息佇列接收訊息 msgrcv;取或送訊息佇列控制資訊 msgctl。
  3. 掌握管道機制中常用的系統呼叫:建立管道檔案 pipe;寫操作 write,讀操作 read。
  4. 瞭解訊號機制中常用的系統呼叫。
  5. 瞭解共享記憶體機制中常用的系統呼叫。

1.共享記憶體的通訊方式

( 1) 有兩個程式,一個是傳送,一個是接收。
傳送程式的程式碼如下:

/*共享記憶體的傳送程式 sndshm.c,先執行傳送程式,再執行接收程式*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<unistd.h>
#include <sys/types.h>
#include <sys/shm.h>
int main() {
	int shmid;
	/*共享記憶體的內部標識*/
	char *viraddr;
	/*定義附接到共享記憶體的虛擬地址*/
	char buffer[BUFSIZ];
	/*建立共享記憶體*/
	shmid = shmget(1234, BUFSIZ, 0666|IPC_CREAT);
	/*附接到程式的虛擬地址空間*/
	viraddr = (char *)shmat(shmid, 0, 0);
	/*迴圈輸入資訊,直到輸入 end 結束*/
	while(1) {
		puts("Enter some text:");
		fgets(buffer, BUFSIZ, stdin);
		strcat(viraddr, buffer);
		/*追加到共享記憶體*/
		if(strncmp(buffer, "end", 3) ==0)
		break;
	}
	shmdt(viraddr);
	/*斷開連結*/
	return 0;
}

接收程式的程式碼如下:

/*共享記憶體的接收程式程式 rcvshm.c*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/shm.h>
int main() {
	int shmid;
	char *viraddr;
	/*獲取共享記憶體*/
	shmid = shmget(1234, BUFSIZ, 0666|IPC_CREAT);
	/*附接到程式的虛擬地址空間*/
	viraddr = (char *)shmat(shmid, 0, 0);
	/*列印資訊內容*/
	printf("your message is :\n %s", viraddr);
	/*斷開連結*/
	shmdt(viraddr);
	/*撤銷共享記憶體*/
	shmctl(shmid, IPC_RMID, 0);
	return 0;
}

捕獲.PNG

2. 訊息佇列的通訊方式

( 1) 訊息佇列通訊方式有兩個程式,一個負責傳送,另一個負責接收。
傳送程式程式碼:

/*傳送訊息程式 sndfile.c*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/msg.h>
#define MAXMSG 512 
/*定義訊息長度*/
/*定義訊息緩衝區佇列中的資料結構*/
struct my_msg {
	long int my_msg_type;
	char some_text[MAXMSG];
}
msg;
int main() {
	int msgid;
	/*定義訊息緩衝區內部標識*/
	char buffer[BUFSIZ];
	/*使用者緩衝區*/
	/*建立訊息佇列*/
	msgid = msgget(1234, 0666|IPC_CREAT);
	/*迴圈向訊息佇列中傳送訊息,直到輸入 end 結束*/
	while(1) {
		puts("Enter some text:");
		fgets(buffer, BUFSIZ, stdin);
		msg.my_msg_type = 1;
		strcpy(msg.some_text, buffer);
		msgsnd(msgid, &msg, MAXMSG, 0);
		/*傳送訊息到緩衝佇列中*/
		if (strncmp(msg.some_text, "end", 3) == 0)
		break;
	}
	return 0;
}

接收程式程式碼:

/*訊息佇列機制的接收程式 rcvfile.c*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/msg.h>
#define MAXMSG 512
struct my_msg {
	long int my_msg_type;
	char some_text[MAXMSG];
}
msg;
int main() {
	int msgid;
	long int msg_to_receive = 0;
	msgid = msgget(1234, 0666|IPC_CREAT);
	/*迴圈從訊息佇列中接收訊息,讀入 end 結束接收*/
	while (1) {
		msgrcv(msgid, &msg, BUFSIZ, msg_to_receive, 0);
		printf("You wrote:%s", msg.some_text);
		if (strncmp(msg.some_text, "end", 3) == 0)
		break;
	}
	msgctl(msgid, IPC_RMID, 0);
	return 0;
}

捕獲2.PNG

3. 管道通訊

/*管道檔案 pipe.c*/
#include <stdio.h>
#include <unistd.h>
int main() {
	int p1, fd[2];
	char outpipe[50];
	/*定義讀緩衝區*/
	char inpipe[50] = "This is a message from child!";
	/*定義寫緩衝區*/
	pipe(fd);
	while ((p1 = fork()) == -1);
	if (p1 == 0) 
	/*子程式中寫*/ {
		write(fd[1], inpipe, 50);
	} else 
	/*父程式中讀*/ {
		wait(0);
		read(fd[0], outpipe, 50);
		printf("%s \n", outpipe);
	}
	return 0;
}

結果:
捕獲3.PNG

4.訊號機制

第一個程式有訊號處理機制

/*signal.c*/
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
void int_func(int sig);
int k;
/*定義迴圈變數*/
void int_func(int sig) {
	k = 0;
}
int main() {
	signal(SIGINT, int_func);
	k = 1;
	while (k == 1) {
		printf("Hello, world!\n");
	}
	printf("OK!\n");
	printf("pid: %d, ppid: %d \n", getpid(), getppid());
}

捕獲4.PNG

5.

相關文章