linux 程序通訊——C語言實現
linux中的程序通訊分為三個部分:低階通訊,管道通訊和程序間通訊IPC(inter process communication)。linux的低階通訊主要用來傳遞程序的控制訊號——檔案鎖和軟中斷訊號機制。linux的程序間通訊IPC有三個部分——①訊號量,②共享記憶體和③訊息佇列。以下是我編寫的linux程序通訊的C語言實現程式碼。作業系統為redhat9.0,編輯器為vi,編譯器採用gcc。下面所有實現程式碼均已經通過測試,執行無誤。
一.低階通訊--訊號通訊
signal.c
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
/*捕捉到訊號sig之後,執行預先預定的動作函式*/
void sig_alarm(int sig)
{
printf("---the signal received is %d. /n", sig);
signal(SIGINT, SIG_DFL); //SIGINT終端中斷訊號,SIG_DFL:恢復預設行為,SIN_IGN:忽略訊號
}
int main()
{
signal(SIGINT, sig_alarm);//捕捉終端中斷訊號
while(1)
{
printf("waiting here!/n");
sleep(1);
}
return 0;
}
二.管道通訊
pipe.c
#include <stdio.h>
#define BUFFER_SIZE 30
int main()
{
int x;
int fd[2];
char buf[BUFFER_SIZE];
char s[BUFFER_SIZE];
pipe(fd);//建立管道
while((x=fork())==-1);//建立管道失敗時,進入迴圈
/*進入子程序,子程序向管道中寫入一個字串*/
if(x==0)
{
sprintf(buf,"This is an example of pipe!/n");
write(fd[1],buf,BUFFER_SIZE);
exit(0);
}
/*進入父程序,父程序從管道的另一端讀出剛才寫入的字串*/
else
{
wait(0);//等待子程序結束
read(fd[0],s,BUFFER_SIZE);//讀出字串,並將其儲存在char s[]中
printf("%s",s);//列印字串
}
return 0;
}
三.程序間通訊——IPC
①訊號量通訊
sem.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
/*聯合體變數*/
union semun
{
int val; //訊號量初始值
struct semid_ds *buf;
unsigned short int *array;
struct seminfo *__buf;
};
/*函式宣告,訊號量定義*/
static int set_semvalue(void); //設定訊號量
static void del_semvalue(void);//刪除訊號量
static int semaphore_p(void); //執行P操作
static int semaphore_v(void); //執行V操作
static int sem_id; //訊號量識別符號
int main(int argc, char *argv[])
{
int i;
int pause_time;
char op_char = 'O';
srand((unsigned int)getpid());
sem_id = semget((key_t)1234, 1, 0666 | IPC_CREAT);//建立一個訊號量,IPC_CREAT表示建立一個新的訊號量
/*如果有引數,設定訊號量,修改字元*/
if (argc > 1)
{
if (!set_semvalue())
{
fprintf(stderr, "Failed to initialize semaphore/n");
exit(EXIT_FAILURE);
}
op_char = 'X';
sleep(5);
}
for(i = 0; i < 10; i++)
{
/*執行P操作*/
if (!semaphore_p())
exit(EXIT_FAILURE);
printf("%c", op_char);
fflush(stdout);
pause_time = rand() % 3;
sleep(pause_time);
printf("%c", op_char);
fflush(stdout);
/*執行V操作*/
if (!semaphore_v())
exit(EXIT_FAILURE);
pause_time = rand() % 2;
sleep(pause_time);
}
printf("/n%d - finished/n", getpid());
if (argc > 1)
{
sleep(10);
del_semvalue(); //刪除訊號量
}
exit(EXIT_SUCCESS);
}
/*設定訊號量*/
static int set_semvalue(void)
{
union semun sem_union;
sem_union.val = 1;
if (semctl(sem_id, 0, SETVAL, sem_union) == -1)
return(0);
return(1);
}
/*刪除訊號量*/
static void del_semvalue(void)
{
union semun sem_union;
if (semctl(sem_id, 0, IPC_RMID, sem_union) == -1)
fprintf(stderr, "Failed to delete semaphore/n");
}
/*執行P操作*/
static int semaphore_p(void)
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = -1; /* P() */
sem_b.sem_flg = SEM_UNDO;
if (semop(sem_id, &sem_b, 1) == -1)
{
fprintf(stderr, "semaphore_p failed/n");
return(0);
}
return(1);
}
/*執行V操作*/
static int semaphore_v(void)
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = 1; /* V() */
sem_b.sem_flg = SEM_UNDO;
if (semop(sem_id, &sem_b, 1) == -1)
{
fprintf(stderr, "semaphore_v failed/n");
return(0);
}
return(1);
}
②訊息佇列通訊
send.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define MAX_TEXT 512
/*用於訊息收發的結構體--my_msg_type:訊息型別,some_text:訊息正文*/
struct my_msg_st
{
long int my_msg_type;
char some_text[MAX_TEXT];
};
int main()
{
int running = 1;//程式執行識別符號
struct my_msg_st some_data;
int msgid;//訊息佇列識別符號
char buffer[BUFSIZ];
/*建立與接受者相同的訊息佇列*/
msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
if (msgid == -1)
{
fprintf(stderr, "msgget failed with error: %d/n", errno);
exit(EXIT_FAILURE);
}
/*向訊息佇列中傳送訊息*/
while(running)
{
printf("Enter some text: ");
fgets(buffer, BUFSIZ, stdin);
some_data.my_msg_type = 1;
strcpy(some_data.some_text, buffer);
if (msgsnd(msgid, (void *)&some_data, MAX_TEXT, 0) == -1)
{
fprintf(stderr, "msgsnd failed/n");
exit(EXIT_FAILURE);
}
if (strncmp(buffer, "end", 3) == 0)
{
running = 0;
}
}
exit(EXIT_SUCCESS);
}
receive.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
/*用於訊息收發的結構體--my_msg_type:訊息型別,some_text:訊息正文*/
struct my_msg_st
{
long int my_msg_type;
char some_text[BUFSIZ];
};
int main()
{
int running = 1;//程式執行識別符號
int msgid; //訊息佇列識別符號
struct my_msg_st some_data;
long int msg_to_receive = 0;//接收訊息的型別--0表示msgid佇列上的第一個訊息
/*建立訊息佇列*/
msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
if (msgid == -1)
{
fprintf(stderr, "msgget failed with error: %d/n", errno);
exit(EXIT_FAILURE);
}
/*接收訊息*/
while(running)
{
if (msgrcv(msgid, (void *)&some_data, BUFSIZ,msg_to_receive, 0) == -1)
{
fprintf(stderr, "msgrcv failed with error: %d/n", errno);
exit(EXIT_FAILURE);
}
printf("You wrote: %s", some_data.some_text);
if (strncmp(some_data.some_text, "end", 3) == 0)
{
running = 0;
}
}
/*刪除訊息佇列*/
if (msgctl(msgid, IPC_RMID, 0) == -1)
{
fprintf(stderr, "msgctl(IPC_RMID) failed/n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
③共享記憶體通訊
share.h
#define TEXT_SZ 2048 //申請共享記憶體大小
struct shared_use_st
{
int written_by_you; //written_by_you為1時表示有資料寫入,為0時表示資料已經被消費者提走
char some_text[TEXT_SZ];
};
producer.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "share.h"
int main()
{
int running = 1; //程式執行標誌位
void *shared_memory = (void *)0;
struct shared_use_st *shared_stuff;
char buffer[BUFSIZ];
int shmid; //共享記憶體識別符號
/*建立共享記憶體*/
shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666 | IPC_CREAT);
if (shmid == -1)
{
fprintf(stderr, "shmget failed/n");
exit(EXIT_FAILURE);
}
/*將共享記憶體連線到一個程序的地址空間中*/
shared_memory = shmat(shmid, (void *)0, 0);//指向共享記憶體第一個位元組的指標
if (shared_memory == (void *)-1)
{
fprintf(stderr, "shmat failed/n");
exit(EXIT_FAILURE);
}
printf("Memory attached at %X/n", (int)shared_memory);
shared_stuff = (struct shared_use_st *)shared_memory;
/*生產者寫入資料*/
while(running)
{
while(shared_stuff->written_by_you == 1)
{
sleep(1);
printf("waiting for client.../n");
}
printf("Enter some text: ");
fgets(buffer, BUFSIZ, stdin);
strncpy(shared_stuff->some_text, buffer, TEXT_SZ);
shared_stuff->written_by_you = 1;
if (strncmp(buffer, "end", 3) == 0)
{
running = 0;
}
}
/*該函式用來將共享記憶體從當前程序中分離,僅使得當前程序不再能使用該共享記憶體*/
if (shmdt(shared_memory) == -1)
{
fprintf(stderr, "shmdt failed/n");
exit(EXIT_FAILURE);
}
printf("producer exit./n");
exit(EXIT_SUCCESS);
}
customer.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "share.h"
int main()
{
int running = 1;//程式執行標誌位
void *shared_memory = (void *)0;
struct shared_use_st *shared_stuff;
int shmid; //共享記憶體識別符號
srand((unsigned int)getpid());
/*建立共享記憶體*/
shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666 | IPC_CREAT);
if (shmid == -1)
{
fprintf(stderr, "shmget failed/n");
exit(EXIT_FAILURE);
}
/*將共享記憶體連線到一個程序的地址空間中*/
shared_memory = shmat(shmid, (void *)0, 0);//指向共享記憶體第一個位元組的指標
if (shared_memory == (void *)-1)
{
fprintf(stderr, "shmat failed/n");
exit(EXIT_FAILURE);
}
printf("Memory attached at %X/n", (int)shared_memory);
shared_stuff = (struct shared_use_st *)shared_memory;
shared_stuff->written_by_you = 0;
/*消費者讀取資料*/
while(running)
{
if (shared_stuff->written_by_you)
{
printf("You wrote: %s", shared_stuff->some_text);
sleep( rand() % 4 );
shared_stuff->written_by_you = 0;
if (strncmp(shared_stuff->some_text, "end", 3) == 0)
{
running = 0;
}
}
}
/*該函式用來將共享記憶體從當前程序中分離,僅使得當前程序不再能使用該共享記憶體*/
if (shmdt(shared_memory) == -1)
{
fprintf(stderr, "shmdt failed/n");
exit(EXIT_FAILURE);
}
/*將共享記憶體刪除,所有程序均不能再訪問該共享記憶體*/
if (shmctl(shmid, IPC_RMID, 0) == -1)
{
fprintf(stderr, "shmctl(IPC_RMID) failed/n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
相關推薦
linux 程序通訊——C語言實現
linux中的程序通訊分為三個部分:低階通訊,管道通訊和程序間通訊IPC(inter process communication)。linux的低階通訊主要用來傳遞程序的控制訊號——檔案鎖和軟中斷訊號機制。linux的程序間通訊IPC有三個部分——①訊號量,②共
Linux終端程序用c語言實現改變輸出的字的顏色
光標位置 高亮 AI 藍色 屬性 用c語言實現 TE c語言 說明 顏色代碼: 格式: echo "\033[字背景顏色;字體顏色m字符串\033[0m" 例如: echo "\033[41;36m something here \033[0m" 其中41的位置代表
Word Count程序(C語言實現)
地址 組成 other 進一步 and 文件遍歷 stand evel oid Word Count 程序 GitHub地址:https://github.com/MansonYe/Word-Count 一、項目簡介 Word Count 是用以統計文本文件的字符數
Linux下用c語言實現發送http請求 方式可以Get或者Post例程參考
sockaddr select sleep online 創建 線程終止 index -s lse [1].[代碼] Linux下用c語言實現發送http請求 方式可以Get或者Post 跳至 [1] ? 1 2 3 4 5 6 7 8 9 10 11 12 1
Linux下用c語言實現傳送http請求 方式可以Get或者Post例程參考
[1].[程式碼] Linux下用c語言實現傳送http請求 方式可以Get或者Post 跳至 [1] ? 1 2
Linux下用c語言實現傳送http請求
前言 在linux下,使用socket進行程式設計,需要到伺服器上進行獲取資料,伺服器使用的php程式設計,需要使用http的方式進行獲取資料。 程式碼 #include <stdio.h> #include <string.h&
linux 環境下 c語言實現mysql資料庫圖片的儲存以及多資料庫直接的轉存
作為一個程式設計師,CSDN對我的程式設計帶來了很多幫助和提高,在這裡可以讓你找到很多開發過程中遇到的問題的解決辦法,今天也寫點自己積累的東西跟大家分享一下,希望對需要的人有幫助. 資料背景: 之前專案一直使用Oracle資料,最近換工作,公司使用的為
linux環境下C語言實現非阻塞方式讀取字串資料的串列埠測試程式,即串列埠工具的編寫
一、前言 1.1 關於串列埠測試工具,網上已經有整合好的應用程式提供大家使用,但其只提供功能介面,內部具體怎麼實現的還需要自己去探索; 1.2 關於串列埠通訊的測試程式在網上已經是數見不鮮,但也不排除很多是直接“參考”別人的(ctrl+c),而且很多程式
linux下使用C語言實現簡易的學生資訊管理系統
該專案資料儲存方式使用的是動態陣列,所以需要用到動態陣列庫,具體庫檔案參考->我的動態陣列庫<-上的兩個檔案 ArrayLib.h 和 ArrayLib.c 學生管理系統的檔案有三個 main.c、stuSystem.h 和 stuSystem.c,
linux下使用C語言實現比較漂亮的字元介面的五子棋遊戲
此專案總共檔案3個檔案 main.c、fiveChess.h 和 fiveChess.c,需要放到同一目錄下編譯 main.c /******************************************************* * 檔名: ma
【C語言實現串列埠通訊知識點整理(四)】關於執行緒和程序
轉載:https://www.cnblogs.com/fuchongjundream/p/3829508.html 因為在外部檔案中呼叫結構體沒有用extern修飾,導致獲取不到正確的值,一直糾結線上程上。現在大概總結執行緒和程序的特點: 概念 1、程序(process) 狹義定義:
linux中編譯C語言程序
編輯器 ins spa include all 運行程序 gcc linux中 style 1.首先安裝gcc編輯器 yum install gcc* -y 2.編寫C語言程序 [[email protected]/* */ ~]# vim aa.c #i
C語言實現24點程序
項目 四則運算 return 輸出 存儲 數據 value class 教材 一、簡介 本程序的思想和算法來自於C語言教材後的實訓項目,程序通過用戶輸入四個整數計算出能夠通過加減乘除得到數字24的所有表達式,程序的設計有別於一般
C語言實現的圖的深度搜索與廣度搜索程序
scan 實現 圖的鄰接表存儲 class dfs c語言 return 並查集 OS /* 上機試驗5-圖的建立和遍歷 1)建立【無向】【非連通】圖的鄰接表存儲結構,要求頂點個數不少於15個。 2)用DFS及BFS對此鄰接表進行遍歷,打印出兩種遍歷的頂點訪問順序。 3)給
c語言實現linux下高危函式system (簡易V1.0版本)
system這個函式真的是要慎用,一不小心就會留下漏洞。 下面是用c語言簡易的實現了一下system函式 #include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<err
(排序演算法)linux c語言實現選擇排序演算法(氣泡排序的略微改進版)
快速排序演算法和氣泡排序演算法是差不多的,都是要兩層迴圈,外迴圈是要比較的個數,其實就是元素的個數,內迴圈就是外層那個標記和其他的比較大小, 氣泡排序是相鄰的兩個,兩兩比較,最後交換出一個最大或者最小值, 快速排序是在氣泡排序的基礎上,找出那個最小的或者最大的,但是不是直接交換,
(排序演算法)linux c語言實現快速排序(氣泡排序的改進版)
快速排序演算法是對氣泡排序演算法的一種改進,氣泡排序是對單個元素的升降,快速排序是對所有元素的升降,不過這個升降是取了某一個標準的前提下,在本文程式碼中,就以a[i],其實就是以最左邊的元素為參考,比較交換之後,將這個參考元素放到分界的地方,即i的位置。 程式碼如下,裡面有比較詳細的
(排序演算法)linux c語言實現二分插入排序演算法(簡化版本的插入排序演算法)
二分插入演算法是在已經排序好的序列裡插入一個元素,是穩定的演算法,關鍵詞是折中。 比如說我要在12345678910裡插入一個3,那麼我先看看中間的數比3大,還是比3小,要是比3大,我就去後一半,如果是比3小,我就去前一半,現在進入某個一半後,再做如此操作,最後將其他的元素依次往後挪
【C語言實現串列埠通訊知識點整理(三)】串列埠開啟、設定資料成功後進行資料讀寫
int OpenDev(char *Dev) { int fd = open(Dev,O_RDWR | O_NOCTTY | O_NONBLOCK); if(-1 == fd) { perror("Can't Open Serial Port"); return -1;
【C語言實現串列埠通訊知識點整理(二)】遇到的問題整理(待續....)
1.c編譯錯誤--error:stray \357 in program UTF-8編碼問題。UTF-8編碼有BOM和無BOM格式。BOM,ByteOrderMark(位元組標記順序),表明使用UTF8來進行編碼。UTF-8的BOM通常為3個位元組EF BB BF。轉換成對應的字元檢視,就是‘\