大家好,我是ST。
今天主要聊一聊,如何使用Linux系統(tǒng)下的msg實(shí)現(xiàn)銀行終端系統(tǒng)的模擬及運(yùn)行。
第一:msg基本簡(jiǎn)介
????Linux系統(tǒng)中IPC通信有多種方式,msg是其中的一種通信方式,稱為消息隊(duì)列。Linux系統(tǒng)中可以通過ipcs -q來查看所有存在的消息隊(duì)列。
????消息隊(duì)列與FIFO很類似,都是一個(gè)隊(duì)列結(jié)構(gòu),并可以實(shí)現(xiàn)多進(jìn)程往隊(duì)列寫入信息,以及多進(jìn)程可以從隊(duì)列里面讀取信息。但是FIFO需要讀寫兩個(gè)端口,事先要打開,這樣才能正常傳遞消息。而消息隊(duì)列可以事先往隊(duì)列里面寫入消息,或者需要時(shí)候再打開,讀取消息。
?????注意:消息隊(duì)列提供了一個(gè)從一個(gè)進(jìn)程往另外一個(gè)進(jìn)程發(fā)送數(shù)據(jù)塊的方法,并且每個(gè)數(shù)據(jù)塊可以包含多個(gè)數(shù)據(jù)類型,接收的進(jìn)程可以獨(dú)立接收不同的數(shù)據(jù)類型。
第二:Linux內(nèi)核中msg相關(guān)的API函數(shù)
#include
?第三:銀行終端系統(tǒng)的實(shí)現(xiàn)原理
補(bǔ)充項(xiàng):服務(wù)器開啟時(shí)負(fù)責(zé)創(chuàng)建兩個(gè)消息隊(duì)列,退出時(shí)銷毀所有子進(jìn)程以及兩個(gè)消息隊(duì)列。
第四:銀行終端系統(tǒng)的實(shí)現(xiàn)步驟
?一、程序設(shè)計(jì)思路
分為兩個(gè)模塊:1.服務(wù)器 2.客戶端
1.服務(wù)器要做的工作就是,在運(yùn)行服務(wù)器的時(shí)候讓服務(wù)器去啟動(dòng)各個(gè)進(jìn)程,開戶,存款,查詢,銷戶...,可以使用vfork+execl去實(shí)現(xiàn),(要保證服務(wù)器一直在運(yùn)行不能讓服務(wù)器退出),由于服務(wù)器要啟動(dòng)每一個(gè)進(jìn)程所以采用for循環(huán)語(yǔ)句可以定義一個(gè)結(jié)構(gòu)體去填寫每一個(gè)需要啟動(dòng)的進(jìn)程的路徑以及名字execl()函數(shù)啟動(dòng)。服務(wù)器退出的時(shí)候要?dú)⑺烂恳粋€(gè)進(jìn)程以及刪除消息隊(duì)列。
2.客戶端主要實(shí)現(xiàn)各個(gè)函數(shù)功能的調(diào)用菜單的編寫,采用模塊化編程的方式去寫代碼,每一個(gè)模塊分別編寫一個(gè).c文件這樣方便調(diào)試和管理,進(jìn)程之間的通信采用消息隊(duì)列的方式通信,每一個(gè)進(jìn)程所發(fā)的消息可以采用消息隊(duì)列結(jié)構(gòu)體中的消息類型來區(qū)分,將每一個(gè)用戶的信息都保存成一個(gè)文件,方便后期的信息查詢,(如果有同學(xué)學(xué)了數(shù)據(jù)庫(kù)可以將每一位用戶的信息都保存到數(shù)據(jù)中)用戶在開戶的時(shí)候,賬號(hào)如果不想采用順序分配(本次系統(tǒng)采用的是順序分配),也可以采用srand((unsigned int)time(NULL))+rand()去進(jìn)行隨機(jī)分配。
二、流程圖設(shè)計(jì)
三、編寫代碼
?
//服務(wù)器 static int g_reqid = -1;//請(qǐng)求消息隊(duì)列 static int g_resid = -1;//響應(yīng)消息隊(duì)列 typedef struct tag_Service { ? ? char ?srv_path[PATH_MAX+1]; ? ? pid_t srv_pid; } ? SERVICE; static SERVICE g_srv[] = { ? ? {"./open", ? ? -1}, ? ? {"./close", ? ?-1}, ? ? {"./save", ? ? -1}, ? ? {"./withdraw", -1}, ? ? {"./query", ? ?-1}, ? ? {"./transfer", -1} }; int init (void) { ? ? printf ("服務(wù)器初始化... "); ? ? //創(chuàng)建請(qǐng)求消息隊(duì)列 ? ? if ((g_reqid = msgget (KEY_REQUEST, ? ? ? ? 0600 | IPC_CREAT | IPC_EXCL)) == -1) { ? ? ? ? perror ("msgget"); ? ? ? ? return -1; ? ? } ? ? printf ("創(chuàng)建請(qǐng)求消息隊(duì)列成功! "); ? ? //創(chuàng)建響應(yīng)消息隊(duì)列 ? ? if ((g_resid = msgget (KEY_RESPOND, ? ? ? ? 0600 | IPC_CREAT | IPC_EXCL)) == -1) { ? ? ? ? perror ("msgget"); ? ? ? ? return -1; ? ? } ? ? printf ("創(chuàng)建響應(yīng)消息隊(duì)列成功! "); ? ? return 0; } void deinit (void) { ? ? printf ("服務(wù)器終結(jié)化... "); ? ? if (msgctl (g_reqid, IPC_RMID, NULL) == -1) ? ? ? ? perror ("msgctl"); ? ? else ? ? ? ? printf ("銷毀請(qǐng)求消息隊(duì)列成功! "); ? ? if (msgctl (g_resid, IPC_RMID, NULL) == -1) ? ? ? ? perror ("msgctl"); ? ? else ? ? ? ? printf ("銷毀響應(yīng)消息隊(duì)列成功! "); } int start (void) { ? ? printf ("啟動(dòng)業(yè)務(wù)服務(wù)... "); ? ? size_t i; ? ? //利用for循環(huán)的去vfork幾個(gè)子進(jìn)程 ? ? for (i = 0; i < sizeof (g_srv) / sizeof (g_srv[0]); i++) { ? ? ? ? if ((g_srv[i].srv_pid = vfork ()) == -1) { ? ? ? ? ? ? perror ("vfork"); ? ? ? ? ? ? return -1; ? ? ? ? } ? ? ? ? //調(diào)用execl函數(shù)去循環(huán)的啟動(dòng)每一個(gè)可執(zhí)行的進(jìn)程 ? ? ? ? if (g_srv[i].srv_pid == 0) { ? ? ? ? ? ? if (execl (g_srv[i].srv_path, g_srv[i].srv_path, ? ? ? ? ? ? ? ? NULL) == -1) { ? ? ? ? ? ? ? ? perror ("execl"); ? ? ? ? ? ? ? ? return -1; ? ? ? ? ? ? } ? ? ? ? ? ? return 0; ? ? ? ? } ? ? } ? ? return 0; } int stop (void) { ? ? printf ("停止業(yè)務(wù)服務(wù)... "); ? ? size_t i; ? ? for (i = 0; i < sizeof (g_srv) / sizeof (g_srv[0]); i++) ? ? ? ? if (kill (g_srv[i].srv_pid, SIGINT) == -1) { ? ? ? ? ? ? perror ("kill"); ? ? ? ? ? ? return -1; ? ? ? ? } ? ? for (;;) ? ? ? ? if (wait (0) == -1) { ? ? ? ? ? ? if (errno != ECHILD) { ? ? ? ? ? ? ? ? perror ("wait"); ? ? ? ? ? ? ? ? return -1; ? ? ? ? ? ? } ? ? ? ? ? ? break; ? ? ? ? } ? ? return 0; } void sigint(int signum) { ? ? printf("%d ", signum);//打印出信號(hào)量的數(shù)值(2) ? ? stop();//調(diào)用此函數(shù) ? ? exit(0); } int main (void) { ? ? atexit (deinit);// 注冊(cè)終止函數(shù)(即main執(zhí)行結(jié)束后調(diào)用的函數(shù)) ? ? ? ? signal(SIGINT, sigint);//產(chǎn)生ctrl+c信號(hào)的時(shí)候就去執(zhí)行sigint函數(shù) ? ? if (init () == -1) ? ? ? ? return -1; ? ? if (start () == -1) ? ? ? ? return -1; ? ? sleep (1); ? ? printf ("按<回車>退出... "); ? ? getchar (); ? ? if (stop () == -1) ? ? ? ? return -1; ? ? return 0; }
//頭文件bank.h #ifndef _BANK_H #define _BANK_H #include#include #define KEY_REQUEST 0x12345678 #define KEY_RESPOND 0x87654321 #define TYPE_OPEN 8001 #define TYPE_CLOSE 8002 #define TYPE_SAVE 8003 #define TYPE_WITHDRAW 8004 #define TYPE_QUERY 8005 #define TYPE_TRANSFER 8006 //賬戶 typedef struct tag_Account { int id;//ID號(hào) char name[256];//用戶名 char passwd[9];//密碼 double balance;//金額 } ACCOUNT; //開戶時(shí)的結(jié)構(gòu)體 typedef struct tag_OpenRequest { long type;//類型 pid_t pid; char name[256]; char passwd[9]; double balance; } OPEN_REQUEST; //開戶應(yīng)答結(jié)構(gòu)體 typedef struct tag_OpenRespond { long type; char error[512]; int id; } OPEN_RESPOND; //清戶結(jié)構(gòu)體 typedef struct tag_CloseRequest { long type; pid_t pid; int id; char name[256]; char passwd[9]; } CLOSE_REQUEST; //清戶應(yīng)答結(jié)構(gòu)體 typedef struct tag_CloseRespond { long type; char error[512]; double balance; } CLOSE_RESPOND; //存款結(jié)構(gòu)體 typedef struct tag_SaveRequest { long type; pid_t pid; int id; char name[256]; double money; } SAVE_REQUEST; //存款應(yīng)答結(jié)構(gòu)體 typedef struct tag_SaveRespond { long type; char error[512]; double balance; } SAVE_RESPOND; //取款結(jié)構(gòu)體 typedef struct tag_WithdrawRequest { long type; pid_t pid; int id; char name[256]; char passwd[9]; double money; } WITHDRAW_REQUEST; //取款應(yīng)答結(jié)構(gòu)體 typedef struct tag_WithdrawRespond { long type; char error[512]; double balance; } WITHDRAW_RESPOND; //查詢結(jié)構(gòu)體 typedef struct tag_QueryRequest { long type; pid_t pid; int id; char name[256]; char passwd[9]; } QUERY_REQUEST; //查詢應(yīng)答結(jié)構(gòu)體 typedef struct tag_QueryRespond { long type; char error[512]; double balance; } QUERY_RESPOND; //轉(zhuǎn)賬結(jié)構(gòu)體 typedef struct tag_TransferRequest { long type; pid_t pid; int id[2]; char name[2][256]; char passwd[9]; double money; } TRANSFER_REQUEST; //轉(zhuǎn)賬應(yīng)答結(jié)構(gòu)體 typedef struct tag_TransferRespond { long type; char error[512]; double balance; } TRANSFER_RESPOND; #endif // _BANK_H
static int g_reqid = -1; static int g_resid = -1; void menu_loop (int (*menu) (void), int (*on_menu[]) (void), ? ? size_t size) { ? ? for (;;) { ? ? ? ? int id = menu (); ? ? ? ? if (id < 0 || size <= id) ? ? ? ? ? ? printf ("無效選擇! "); ? ? ? ? else if (on_menu[id] () == -1) ? ? ? ? ? ? break; ? ? } } int main_menu (void) { ? ? printf ("-------- "); ? ? printf ("本地銀行 "); ? ? printf ("-------- "); ? ? printf ("[1] 開戶 "); ? ? printf ("[2] 清戶 "); ? ? printf ("[3] 存款 "); ? ? printf ("[4] 取款 "); ? ? printf ("[5] 查詢 "); ? ? printf ("[6] 轉(zhuǎn)賬 "); ? ? printf ("[0] 退出 "); ? ? printf ("-------- "); ? ? printf ("請(qǐng)選擇:"); ? ? int id = -1; ? ? scanf ("%d", &id); ? ? scanf ("%*[^ ]"); ? ? scanf ("%*c"); ? ? return id; } //0 退出 int on_quit (void) { ? ? printf ("謝謝使用,再見! "); ? ? return -1; } //1 開戶 int on_open (void) { ? ? pid_t pid = getpid ();//獲得該進(jìn)程號(hào) ? ? OPEN_REQUEST req = {TYPE_OPEN, pid};//TYPE_OPEN 8001 ? ? printf ("戶名:"); ? ? scanf ("%s", req.name); ? ? printf ("密碼:"); ? ? scanf ("%s", req.passwd); ? ? printf ("金額:"); ? ? scanf ("%lf", &req.balance); ? ? //把消息添加到已打開的請(qǐng)求消息隊(duì)列末尾 ? ? if (msgsnd (g_reqid, &req, sizeof (req) - sizeof (req.type), ? ? ? ? 0) == -1) { ? ? ? ? perror ("msgsnd"); ? ? ? ? return 0; ? ? } ? ? OPEN_RESPOND res;//定義一個(gè)應(yīng)答結(jié)構(gòu)體變量 ? ? //把消息從響應(yīng)消息隊(duì)列中取走 ? ? if (msgrcv (g_resid, &res, sizeof (res) - sizeof (res.type), ? ? ? ? pid, 0) == -1) { ? ? ? ? perror ("msgrcv"); ? ? ? ? return 0; ? ? } ? ? if (strlen (res.error)) { ? ? ? ? printf ("%s ", res.error); ? ? ? ? return 0; ? ? } ? ? printf ("賬號(hào):%d ", res.id); ? ? return 0; } //2 清戶 int on_close (void) { ? ? pid_t pid = getpid (); ? ? CLOSE_REQUEST req = {TYPE_CLOSE, pid}; ? ? printf ("賬號(hào):"); ? ? scanf ("%d", &req.id); ? ? printf ("戶名:"); ? ? scanf ("%s", req.name); ? ? printf ("密碼:"); ? ? scanf ("%s", req.passwd); ? ? if (msgsnd (g_reqid, &req, sizeof (req) - sizeof (req.type), ? ? ? ? 0) == -1) { ? ? ? ? perror ("msgsnd"); ? ? ? ? return 0; ? ? } ? ? CLOSE_RESPOND res; ? ? if (msgrcv (g_resid, &res, sizeof (res) - sizeof (res.type), ? ? ? ? pid, 0) == -1) { ? ? ? ? perror ("msgrcv"); ? ? ? ? return 0; ? ? } ? ? if (strlen (res.error)) { ? ? ? ? printf ("%s ", res.error); ? ? ? ? return 0; ? ? } ? ? printf ("余額:%.2lf ", res.balance); ? ? return 0; } //3 存款 int on_save (void) { ? ? pid_t pid = getpid (); ? ? SAVE_REQUEST req = {TYPE_SAVE, pid}; ? ? printf ("賬號(hào):"); ? ? scanf ("%d", &req.id); ? ? printf ("戶名:"); ? ? scanf ("%s", req.name); ? ? printf ("金額:"); ? ? scanf ("%lf", &req.money); ? ? if (msgsnd (g_reqid, &req, sizeof (req) - sizeof (req.type), ? ? ? ? 0) == -1) { ? ? ? ? perror ("msgsnd"); ? ? ? ? return 0; ? ? } ? ? SAVE_RESPOND res; ? ? if (msgrcv (g_resid, &res, sizeof (res) - sizeof (res.type), ? ? ? ? pid, 0) == -1) { ? ? ? ? perror ("msgrcv"); ? ? ? ? return 0; ? ? } ? ? if (strlen (res.error)) { ? ? ? ? printf ("%s ", res.error); ? ? ? ? return 0; ? ? } ? ? printf ("余額:%.2lf ", res.balance); ? ? return 0; } //4?取款 int on_withdraw (void) { ? ? pid_t pid = getpid (); ? ? WITHDRAW_REQUEST req = {TYPE_WITHDRAW, pid}; ? ? printf ("賬號(hào):"); ? ? scanf ("%d", &req.id); ? ? printf ("戶名:"); ? ? scanf ("%s", req.name); ? ? printf ("密碼:"); ? ? scanf ("%s", req.passwd); ? ? printf ("金額:"); ? ? scanf ("%lf", &req.money); ? ? if (msgsnd (g_reqid, &req, sizeof (req) - sizeof (req.type), ? ? ? ? 0) == -1) { ? ? ? ? perror ("msgsnd"); ? ? ? ? return 0; ? ? } ? ? WITHDRAW_RESPOND res; ? ? if (msgrcv (g_resid, &res, sizeof (res) - sizeof (res.type), ? ? ? ? pid, 0) == -1) { ? ? ? ? perror ("msgrcv"); ? ? ? ? return 0; ? ? } ? ? if (strlen (res.error)) { ? ? ? ? printf ("%s ", res.error); ? ? ? ? return 0; ? ? } ? ? printf ("余額:%.2lf ", res.balance); ? ? return 0; } //5 查詢 int on_query (void) { ? ? pid_t pid = getpid (); ? ? QUERY_REQUEST req = {TYPE_QUERY, pid}; ? ? printf ("賬號(hào):"); ? ? scanf ("%d", &req.id); ? ? printf ("戶名:"); ? ? scanf ("%s", req.name); ? ? printf ("密碼:"); ? ? scanf ("%s", req.passwd); ? ? if (msgsnd (g_reqid, &req, sizeof (req) - sizeof (req.type), ? ? ? ? 0) == -1) { ? ? ? ? perror ("msgsnd"); ? ? ? ? return 0; ? ? } ? ? QUERY_RESPOND res; ? ? if (msgrcv (g_resid, &res, sizeof (res) - sizeof (res.type), ? ? ? ? pid, 0) == -1) { ? ? ? ? perror ("msgrcv"); ? ? ? ? return 0; ? ? } ? ? if (strlen (res.error)) { ? ? ? ? printf ("%s ", res.error); ? ? ? ? return 0; ? ? } ? ? printf ("余額:%.2lf ", res.balance); ? ? return 0; } //6 轉(zhuǎn)賬 int on_transfer (void) { ? ? pid_t pid = getpid (); ? ? TRANSFER_REQUEST req = {TYPE_TRANSFER, pid}; ? ? printf ("賬號(hào):"); ? ? scanf ("%d", &req.id[0]); ? ? printf ("戶名:"); ? ? scanf ("%s", req.name[0]); ? ? printf ("密碼:"); ? ? scanf ("%s", req.passwd); ? ? printf ("金額:"); ? ? scanf ("%lf", &req.money); ? ? printf ("對(duì)方賬號(hào):"); ? ? scanf ("%d", &req.id[1]); ? ? printf ("對(duì)方戶名:"); ? ? scanf ("%s", req.name[1]); ? ? if (msgsnd (g_reqid, &req, sizeof (req) - sizeof (req.type), ? ? ? ? 0) == -1) { ? ? ? ? perror ("msgsnd"); ? ? ? ? return 0; ? ? } ? ? TRANSFER_RESPOND res; ? ? if (msgrcv (g_resid, &res, sizeof (res) - sizeof (res.type), ? ? ? ? pid, 0) == -1) { ? ? ? ? perror ("msgrcv"); ? ? ? ? return 0; ? ? } ? ? if (strlen (res.error)) { ? ? ? ? printf ("%s ", res.error); ? ? ? ? return 0; ? ? } ? ? printf ("余額:%.2lf ", res.balance); ? ? return 0; } int main (void) { ? ? if ((g_reqid = msgget (KEY_REQUEST, 0)) == -1) {//發(fā)送請(qǐng)求消息隊(duì)列 ? ? ? ? perror ("msgget"); ? ? ? ? return -1; ? ? } ? ? if ((g_resid = msgget (KEY_RESPOND, 0)) == -1) {//獲得響應(yīng)消息隊(duì)列 ? ? ? ? perror ("msgget"); ? ? ? ? return -1; ? ? } //定義函數(shù)指針數(shù)組 ? ? int (*on_menu[]) (void) = {on_quit, on_open, on_close, ? ? ? ? on_save, on_withdraw, on_query, on_transfer}; ? ? menu_loop (main_menu, on_menu, ? ? ? ? sizeof (on_menu) / sizeof (on_menu[0])); ? ? return 0; }
//開戶子進(jìn)程(open.c) void sigint (int signum) { ? ? printf ("開戶服務(wù):即將停止。 "); ? ? exit (0); } int main (void) { ? ? if (signal (SIGINT, sigint) == SIG_ERR) {//產(chǎn)生ctrl+c信號(hào)的時(shí)候就去執(zhí)行sigint函數(shù) ? ? ? ? perror ("signal"); ? ? ? ? return -1; ? ? } ? ? //獲得消息隊(duì)列 ? ? int reqid = msgget (KEY_REQUEST, 0); ? ? if (reqid == -1) { ? ? ? ? perror ("msgget"); ? ? ? ? return -1; ? ? } ? ? //獲得相應(yīng)消息隊(duì)列 ? ? int resid = msgget (KEY_RESPOND, 0); ? ? if (resid == -1) { ? ? ? ? perror ("msgget"); ? ? ? ? return -1; ? ? } ? ? printf ("開戶服務(wù):?jiǎn)?dòng)就緒。 "); ? ? for (;;) { ? ? ? ? OPEN_REQUEST req; ? ? ? ? if (msgrcv (reqid, &req, sizeof (req) - sizeof (req.type), ? ? ? ? ? ? TYPE_OPEN, 0) == -1) { ? ? ? ? ? ? perror ("msgrcv"); ? ? ? ? ? ? continue; ? ? ? ? } ? ? ? ? OPEN_RESPOND res = {req.pid, ""}; ? ? ? ? ACCOUNT acc; ? ? ? ? if ((acc.id = genid ()) == -1) { ? ? ? ? ? ? sprintf (res.error, "創(chuàng)立賬戶失?。?); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? strcpy (acc.name, req.name); ? ? ? ? strcpy (acc.passwd, req.passwd); ? ? ? ? acc.balance = req.balance; ? ? ? ? if (save (&acc) == -1) { ? ? ? ? ? ? sprintf (res.error, "保存賬戶失?。?); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? res.id = acc.id; send_respond: ? ? ? ? if (msgsnd (resid, &res, sizeof (res) - sizeof (res.type), ? ? ? ? ? ? 0) == -1) { ? ? ? ? ? ? perror ("msgsnd"); ? ? ? ? ? ? continue; ? ? ? ? } ? ? } ? ? return 0; }
//銷戶子進(jìn)程(close.c) void sigint (int signum) { ? ? printf ("清戶服務(wù):即將停止。 "); ? ? exit (0); } int main (void) { ? ? if (signal (SIGINT, sigint) == SIG_ERR) { ? ? ? ? perror ("signal"); ? ? ? ? return -1; ? ? } ? ? int reqid = msgget (KEY_REQUEST, 0); ? ? if (reqid == -1) { ? ? ? ? perror ("msgget"); ? ? ? ? return -1; ? ? } ? ? int resid = msgget (KEY_RESPOND, 0); ? ? if (resid == -1) { ? ? ? ? perror ("msgget"); ? ? ? ? return -1; ? ? } ? ? printf ("清戶服務(wù):?jiǎn)?dòng)就緒。 "); ? ? for (;;) { ? ? ? ? CLOSE_REQUEST req; ? ? ? ? if (msgrcv (reqid, &req, sizeof (req) - sizeof (req.type), ? ? ? ? ? ? TYPE_CLOSE, 0) == -1) { ? ? ? ? ? ? perror ("msgrcv"); ? ? ? ? ? ? continue; ? ? ? ? } ? ? ? ? CLOSE_RESPOND res = {req.pid, ""}; ? ? ? ? ACCOUNT acc; ? ? ? ? if (get (req.id, &acc) == -1) { ? ? ? ? ? ? sprintf (res.error, "無效賬號(hào)!"); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? if (strcmp (req.name, acc.name)) { ? ? ? ? ? ? sprintf (res.error, "無效戶名!"); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? if (strcmp (req.passwd, acc.passwd)) { ? ? ? ? ? ? sprintf (res.error, "密碼錯(cuò)誤!"); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? if (delete (req.id) == -1) { ? ? ? ? ? ? sprintf (res.error, "刪除賬戶失敗!"); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? res.balance = acc.balance; send_respond: ? ? ? ? if (msgsnd (resid, &res, sizeof (res) - sizeof (res.type), ? ? ? ? ? ? 0) == -1) { ? ? ? ? ? ? perror ("msgsnd"); ? ? ? ? ? ? continue; ? ? ? ? } ? ? } ? ? return 0; }
//存款子進(jìn)程(save.c) void sigint (int signum) { ? ? printf ("清戶服務(wù):即將停止。 "); ? ? exit (0); } int main (void) { ? ? if (signal (SIGINT, sigint) == SIG_ERR) { ? ? ? ? perror ("signal"); ? ? ? ? return -1; ? ? } ? ? int reqid = msgget (KEY_REQUEST, 0); ? ? if (reqid == -1) { ? ? ? ? perror ("msgget"); ? ? ? ? return -1; ? ? } ? ? int resid = msgget (KEY_RESPOND, 0); ? ? if (resid == -1) { ? ? ? ? perror ("msgget"); ? ? ? ? return -1; ? ? } ? ? printf ("清戶服務(wù):?jiǎn)?dòng)就緒。 "); ? ? for (;;) { ? ? ? ? CLOSE_REQUEST req; ? ? ? ? if (msgrcv (reqid, &req, sizeof (req) - sizeof (req.type), ? ? ? ? ? ? TYPE_CLOSE, 0) == -1) { ? ? ? ? ? ? perror ("msgrcv"); ? ? ? ? ? ? continue; ? ? ? ? } ? ? ? ? CLOSE_RESPOND res = {req.pid, ""}; ? ? ? ? ACCOUNT acc; ? ? ? ? if (get (req.id, &acc) == -1) { ? ? ? ? ? ? sprintf (res.error, "無效賬號(hào)!"); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? if (strcmp (req.name, acc.name)) { ? ? ? ? ? ? sprintf (res.error, "無效戶名!"); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? if (strcmp (req.passwd, acc.passwd)) { ? ? ? ? ? ? sprintf (res.error, "密碼錯(cuò)誤!"); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? if (delete (req.id) == -1) { ? ? ? ? ? ? sprintf (res.error, "刪除賬戶失?。?); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? res.balance = acc.balance; send_respond: ? ? ? ? if (msgsnd (resid, &res, sizeof (res) - sizeof (res.type), ? ? ? ? ? ? 0) == -1) { ? ? ? ? ? ? perror ("msgsnd"); ? ? ? ? ? ? continue; ? ? ? ? } ? ? } ? ? return 0; }
//取款子進(jìn)程(withdraw.c) void?sigint?(int?signum)?{ ? ? printf ("取款服務(wù):即將停止。 "); ? ? exit (0); } int main (void) { ? ? if (signal (SIGINT, sigint) == SIG_ERR) { ? ? ? ? perror ("signal"); ? ? ? ? return -1; ? ? } ? ? int reqid = msgget (KEY_REQUEST, 0); ? ? if (reqid == -1) { ? ? ? ? perror ("msgget"); ? ? ? ? return -1; ? ? } ? ? int resid = msgget (KEY_RESPOND, 0); ? ? if (resid == -1) { ? ? ? ? perror ("msgget"); ? ? ? ? return -1; ? ? } ? ? printf ("取款服務(wù):?jiǎn)?dòng)就緒。 "); ? ? for (;;) { ? ? ? ? WITHDRAW_REQUEST req; ? ? ? ? if (msgrcv (reqid, &req, sizeof (req) - sizeof (req.type), ? ? ? ? ? ? TYPE_WITHDRAW, 0) == -1) { ? ? ? ? ? ? perror ("msgrcv"); ? ? ? ? ? ? continue; ? ? ? ? } ? ? ? ? WITHDRAW_RESPOND res = {req.pid, ""}; ? ? ? ? ACCOUNT acc; ? ? ? ? if (get (req.id, &acc) == -1) { ? ? ? ? ? ? sprintf (res.error, "無效賬號(hào)!"); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? if (strcmp (req.name, acc.name)) { ? ? ? ? ? ? sprintf (res.error, "無效戶名!"); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? if (strcmp (req.passwd, acc.passwd)) { ? ? ? ? ? ? sprintf (res.error, "密碼錯(cuò)誤!"); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? if (req.money > acc.balance) { ? ? ? ? ? ? sprintf (res.error, "余額不足!"); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? acc.balance -= req.money; ? ? ? ? if (update (&acc) == -1) { ? ? ? ? ? ? sprintf (res.error, "更新賬戶失敗!"); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? res.balance = acc.balance; send_respond: ? ? ? ? if (msgsnd (resid, &res, sizeof (res) - sizeof (res.type), ? ? ? ? ? ? 0) == -1) { ? ? ? ? ? ? perror ("msgsnd"); ? ? ? ? ? ? continue; ? ? ? ? } ? ? } ? ? return 0; }
//查詢子進(jìn)程(query.c) void sigint (int signum) { ? ? printf ("查詢服務(wù):即將停止。 "); ? ? exit (0); } int main (void) { ? ? if (signal (SIGINT, sigint) == SIG_ERR) { ? ? ? ? perror ("signal"); ? ? ? ? return -1; ? ? } ? ? int reqid = msgget (KEY_REQUEST, 0); ? ? if (reqid == -1) { ? ? ? ? perror ("msgget"); ? ? ? ? return -1; ? ? } ? ? int resid = msgget (KEY_RESPOND, 0); ? ? if (resid == -1) { ? ? ? ? perror ("msgget"); ? ? ? ? return -1; ? ? } ? ? printf ("查詢服務(wù):?jiǎn)?dòng)就緒。 "); ? ? for (;;) { ? ? ? ? QUERY_REQUEST req; ? ? ? ? if (msgrcv (reqid, &req, sizeof (req) - sizeof (req.type), ? ? ? ? ? ? TYPE_QUERY, 0) == -1) { ? ? ? ? ? ? perror ("msgrcv"); ? ? ? ? ? ? continue; ? ? ? ? } ? ? ? ? QUERY_RESPOND res = {req.pid, ""}; ? ? ? ? ACCOUNT acc; ? ? ? ? if (get (req.id, &acc) == -1) { ? ? ? ? ? ? sprintf (res.error, "無效賬號(hào)!"); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? if (strcmp (req.name, acc.name)) { ? ? ? ? ? ? sprintf (res.error, "無效戶名!"); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? if (strcmp (req.passwd, acc.passwd)) { ? ? ? ? ? ? sprintf (res.error, "密碼錯(cuò)誤!"); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? res.balance = acc.balance; send_respond: ? ? ? ? if (msgsnd (resid, &res, sizeof (res) - sizeof (res.type), ? ? ? ? ? ? 0) == -1) { ? ? ? ? ? ? perror ("msgsnd"); ? ? ? ? ? ? continue; ? ? ? ? } ? ? } ? ? return 0; }
//轉(zhuǎn)賬子進(jìn)程(transfer) void sigint (int signum) { ? ? printf ("轉(zhuǎn)賬服務(wù):即將停止。 "); ? ? exit (0); } int main (void) { ? ? if (signal (SIGINT, sigint) == SIG_ERR) { ? ? ? ? perror ("signal"); ? ? ? ? return -1; ? ? } ? ? int reqid = msgget (KEY_REQUEST, 0); ? ? if (reqid == -1) { ? ? ? ? perror ("msgget"); ? ? ? ? return -1; ? ? } ? ? int resid = msgget (KEY_RESPOND, 0); ? ? if (resid == -1) { ? ? ? ? perror ("msgget"); ? ? ? ? return -1; ? ? } ? ? printf ("轉(zhuǎn)賬服務(wù):?jiǎn)?dòng)就緒。 "); ? ? for (;;) { ? ? ? ? TRANSFER_REQUEST req; ? ? ? ? if (msgrcv (reqid, &req, sizeof (req) - sizeof (req.type), ? ? ? ? ? ? TYPE_TRANSFER, 0) == -1) { ? ? ? ? ? ? perror ("msgrcv"); ? ? ? ? ? ? continue; ? ? ? ? } ? ? ? ? TRANSFER_RESPOND res = {req.pid, ""}; ? ? ? ? ACCOUNT acc[2]; ? ? ? ? if (get (req.id[0], &acc[0]) == -1) { ? ? ? ? ? ? sprintf (res.error, "無效賬號(hào)!"); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? if (strcmp (req.name[0], acc[0].name)) { ? ? ? ? ? ? sprintf (res.error, "無效戶名!"); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? if (strcmp (req.passwd, acc[0].passwd)) { ? ? ? ? ? ? sprintf (res.error, "密碼錯(cuò)誤!"); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? if (req.money > acc[0].balance) { ? ? ? ? ? ? sprintf (res.error, "余額不足!"); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? if (get (req.id[1], &acc[1]) == -1) { ? ? ? ? ? ? sprintf (res.error, "無效對(duì)方賬號(hào)!"); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? if (strcmp (req.name[1], acc[1].name)) { ? ? ? ? ? ? sprintf (res.error, "無效對(duì)方戶名!"); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? acc[0].balance -= req.money; ? ? ? ? if (update (&acc[0]) == -1) { ? ? ? ? ? ? sprintf (res.error, "更新賬戶失敗!"); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? acc[1].balance += req.money; ? ? ? ? if (update (&acc[1]) == -1) { ? ? ? ? ? ? sprintf (res.error, "更新對(duì)方賬戶失??!"); ? ? ? ? ? ? goto send_respond; ? ? ? ? } ? ? ? ? res.balance = acc[0].balance; send_respond: ? ? ? ? if (msgsnd (resid, &res, sizeof (res) - sizeof (res.type), ? ? ? ? ? ? 0) == -1) { ? ? ? ? ? ? perror ("msgsnd"); ? ? ? ? ? ? continue; ? ? ? ? } ? ? } ? ? return 0; }
//封裝的庫(kù)(lib.c) const char* ID_FILE = "id.dat"; int genid (void) { ? ? int id = 1000; ? ? int fd = open (ID_FILE, O_RDWR | O_CREAT, 0644); ? ? if (fd == -1) { ? ? ? ? perror ("open"); ? ? ? ? return -1; ? ? } ? ? if (read (fd, &id, sizeof (id)) == -1) { ? ? ? ? perror ("read"); ? ? ? ? return -1; ? ? } ? ? id++; ? ? if (lseek (fd, 0, SEEK_SET) == -1) { ? ? ? ? perror ("lseek"); ? ? ? ? return -1; ? ? } ? ? if (write (fd, &id, sizeof (id)) == -1) { ? ? ? ? perror ("write"); ? ? ? ? return -1; ? ? } ? ? close (fd); ? ? return id; } int save (const ACCOUNT* acc) { ? ? char pathname[PATH_MAX+1]; ? ? sprintf (pathname, "%d.acc", acc -> id); ? ? int fd = creat (pathname, 0644); ? ? if (fd == -1) { ? ? ? ? perror ("creat"); ? ? ? ? return -1; ? ? } ? ? if (write (fd, acc, sizeof (*acc)) == -1) { ? ? ? ? perror ("write"); ? ? ? ? return -1; ? ? } ? ? close (fd); ? ? return 0; } int get (int id, ACCOUNT* acc) { ? ? char pathname[PATH_MAX+1]; ? ? sprintf (pathname, "%d.acc", id); ? ? int fd = open (pathname, O_RDONLY); ? ? if (fd == -1) { ? ? ? ? perror ("open"); ? ? ? ? return -1; ? ? } ? ? if (read (fd, acc, sizeof (*acc)) == -1) { ? ? ? ? perror ("read"); ? ? ? ? return -1; ? ? } ? ? close (fd); ? ? return 0; } int update (const ACCOUNT* acc) { ? ? char pathname[PATH_MAX+1]; ? ? sprintf (pathname, "%d.acc", acc -> id); ? ? int fd = open (pathname, O_WRONLY); ? ? if (fd == -1) { ? ? ? ? perror ("open"); ? ? ? ? return -1; ? ? } ? ? if (write (fd, acc, sizeof (*acc)) == -1) { ? ? ? ? perror ("write"); ? ? ? ? return -1; ? ? } ? ? close (fd); ? ? return 0; } int delete (int id) { ? ? char pathname[PATH_MAX+1]; ? ? sprintf (pathname, "%d.acc", id); ? ? if (unlink (pathname) == -1) { ? ? ? ? perror ("unlink"); ? ? ? ? return -1; ? ? } ? ? return 0; }
//庫(kù)的聲明(lib.h) #ifndef _LIBFUNC_H #define _LIBFUNC_H #include "../inc/bank.h" int genid (void); int save (const ACCOUNT* acc); int get (int id, ACCOUNT* acc); int update (const ACCOUNT* acc); int delete (int id); #endif // _LIBFUNC_H
?
總結(jié):Linux系統(tǒng)中,msg消息隊(duì)列在多進(jìn)程間通信的使用過程,在實(shí)際開發(fā)中應(yīng)用是非常廣泛的,十分建議初學(xué)Linux編程的工程師們?nèi)ゾ毩?xí)這套系統(tǒng),加深消息隊(duì)列在多進(jìn)程間通信的應(yīng)用,這將具有很大的益處。
評(píng)論
查看更多