大家好,我是ST。
今天主要聊一聊,如何使用Linux系統(tǒng)下的msg實(shí)現(xiàn)銀行終端系統(tǒng)的模擬及運(yùn)行。
第一:msg基本簡介
????Linux系統(tǒng)中IPC通信有多種方式,msg是其中的一種通信方式,稱為消息隊列。Linux系統(tǒng)中可以通過ipcs -q來查看所有存在的消息隊列。

????消息隊列與FIFO很類似,都是一個隊列結(jié)構(gòu),并可以實(shí)現(xiàn)多進(jìn)程往隊列寫入信息,以及多進(jìn)程可以從隊列里面讀取信息。但是FIFO需要讀寫兩個端口,事先要打開,這樣才能正常傳遞消息。而消息隊列可以事先往隊列里面寫入消息,或者需要時候再打開,讀取消息。
?????注意:消息隊列提供了一個從一個進(jìn)程往另外一個進(jìn)程發(fā)送數(shù)據(jù)塊的方法,并且每個數(shù)據(jù)塊可以包含多個數(shù)據(jù)類型,接收的進(jìn)程可以獨(dú)立接收不同的數(shù)據(jù)類型。

第二:Linux內(nèi)核中msg相關(guān)的API函數(shù)
#include
?第三:銀行終端系統(tǒng)的實(shí)現(xiàn)原理

補(bǔ)充項:服務(wù)器開啟時負(fù)責(zé)創(chuàng)建兩個消息隊列,退出時銷毀所有子進(jìn)程以及兩個消息隊列。
第四:銀行終端系統(tǒng)的實(shí)現(xiàn)步驟
?一、程序設(shè)計思路
分為兩個模塊:1.服務(wù)器 2.客戶端
1.服務(wù)器要做的工作就是,在運(yùn)行服務(wù)器的時候讓服務(wù)器去啟動各個進(jìn)程,開戶,存款,查詢,銷戶...,可以使用vfork+execl去實(shí)現(xiàn),(要保證服務(wù)器一直在運(yùn)行不能讓服務(wù)器退出),由于服務(wù)器要啟動每一個進(jìn)程所以采用for循環(huán)語句可以定義一個結(jié)構(gòu)體去填寫每一個需要啟動的進(jìn)程的路徑以及名字execl()函數(shù)啟動。服務(wù)器退出的時候要?dú)⑺烂恳粋€進(jìn)程以及刪除消息隊列。

2.客戶端主要實(shí)現(xiàn)各個函數(shù)功能的調(diào)用菜單的編寫,采用模塊化編程的方式去寫代碼,每一個模塊分別編寫一個.c文件這樣方便調(diào)試和管理,進(jìn)程之間的通信采用消息隊列的方式通信,每一個進(jìn)程所發(fā)的消息可以采用消息隊列結(jié)構(gòu)體中的消息類型來區(qū)分,將每一個用戶的信息都保存成一個文件,方便后期的信息查詢,(如果有同學(xué)學(xué)了數(shù)據(jù)庫可以將每一位用戶的信息都保存到數(shù)據(jù)中)用戶在開戶的時候,賬號如果不想采用順序分配(本次系統(tǒng)采用的是順序分配),也可以采用srand((unsigned int)time(NULL))+rand()去進(jìn)行隨機(jī)分配。

二、流程圖設(shè)計


三、編寫代碼
?
//服務(wù)器 static int g_reqid = -1;//請求消息隊列 static int g_resid = -1;//響應(yīng)消息隊列 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)建請求消息隊列 ? ? if ((g_reqid = msgget (KEY_REQUEST, ? ? ? ? 0600 | IPC_CREAT | IPC_EXCL)) == -1) { ? ? ? ? perror ("msgget"); ? ? ? ? return -1; ? ? } ? ? printf ("創(chuàng)建請求消息隊列成功! "); ? ? //創(chuàng)建響應(yīng)消息隊列 ? ? if ((g_resid = msgget (KEY_RESPOND, ? ? ? ? 0600 | IPC_CREAT | IPC_EXCL)) == -1) { ? ? ? ? perror ("msgget"); ? ? ? ? return -1; ? ? } ? ? printf ("創(chuàng)建響應(yīng)消息隊列成功! "); ? ? return 0; } void deinit (void) { ? ? printf ("服務(wù)器終結(jié)化... "); ? ? if (msgctl (g_reqid, IPC_RMID, NULL) == -1) ? ? ? ? perror ("msgctl"); ? ? else ? ? ? ? printf ("銷毀請求消息隊列成功! "); ? ? if (msgctl (g_resid, IPC_RMID, NULL) == -1) ? ? ? ? perror ("msgctl"); ? ? else ? ? ? ? printf ("銷毀響應(yīng)消息隊列成功! "); } int start (void) { ? ? printf ("啟動業(yè)務(wù)服務(wù)... "); ? ? size_t i; ? ? //利用for循環(huán)的去vfork幾個子進(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)的啟動每一個可執(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);//打印出信號量的數(shù)值(2) ? ? stop();//調(diào)用此函數(shù) ? ? exit(0); } int main (void) { ? ? atexit (deinit);// 注冊終止函數(shù)(即main執(zhí)行結(jié)束后調(diào)用的函數(shù)) ? ? ? ? signal(SIGINT, sigint);//產(chǎn)生ctrl+c信號的時候就去執(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號 char name[256];//用戶名 char passwd[9];//密碼 double balance;//金額 } ACCOUNT; //開戶時的結(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 ("請選擇:");
? ? 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)程號
? ? OPEN_REQUEST req = {TYPE_OPEN, pid};//TYPE_OPEN 8001
? ? printf ("戶名:");
? ? scanf ("%s", req.name);
? ? printf ("密碼:");
? ? scanf ("%s", req.passwd);
? ? printf ("金額:");
? ? scanf ("%lf", &req.balance);
? ? //把消息添加到已打開的請求消息隊列末尾
? ? if (msgsnd (g_reqid, &req, sizeof (req) - sizeof (req.type),
? ? ? ? 0) == -1) {
? ? ? ? perror ("msgsnd");
? ? ? ? return 0;
? ? }
? ? OPEN_RESPOND res;//定義一個應(yīng)答結(jié)構(gòu)體變量
? ? //把消息從響應(yīng)消息隊列中取走
? ? 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 ("賬號:%d
", res.id);
? ? return 0;
}
//2 清戶
int on_close (void) {
? ? pid_t pid = getpid ();
? ? CLOSE_REQUEST req = {TYPE_CLOSE, pid};
? ? printf ("賬號:");
? ? 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 ("賬號:");
? ? 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 ("賬號:");
? ? 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 ("賬號:");
? ? 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 ("賬號:");
? ? scanf ("%d", &req.id[0]);
? ? printf ("戶名:");
? ? scanf ("%s", req.name[0]);
? ? printf ("密碼:");
? ? scanf ("%s", req.passwd);
? ? printf ("金額:");
? ? scanf ("%lf", &req.money);
? ? printf ("對方賬號:");
? ? scanf ("%d", &req.id[1]);
? ? printf ("對方戶名:");
? ? 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ā)送請求消息隊列
? ? ? ? perror ("msgget");
? ? ? ? return -1;
? ? }
? ? if ((g_resid = msgget (KEY_RESPOND, 0)) == -1) {//獲得響應(yīng)消息隊列
? ? ? ? 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信號的時候就去執(zhí)行sigint函數(shù)
? ? ? ? perror ("signal");
? ? ? ? return -1;
? ? }
? ? //獲得消息隊列
? ? int reqid = msgget (KEY_REQUEST, 0);
? ? if (reqid == -1) {
? ? ? ? perror ("msgget");
? ? ? ? return -1;
? ? }
? ? //獲得相應(yīng)消息隊列
? ? int resid = msgget (KEY_RESPOND, 0);
? ? if (resid == -1) {
? ? ? ? perror ("msgget");
? ? ? ? return -1;
? ? }
? ? printf ("開戶服務(wù):啟動就緒。
");
? ? 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ù):啟動就緒。
");
? ? 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, "無效賬號!");
? ? ? ? ? ? goto send_respond;
? ? ? ? }
? ? ? ? if (strcmp (req.name, acc.name)) {
? ? ? ? ? ? sprintf (res.error, "無效戶名!");
? ? ? ? ? ? goto send_respond;
? ? ? ? }
? ? ? ? if (strcmp (req.passwd, acc.passwd)) {
? ? ? ? ? ? sprintf (res.error, "密碼錯誤!");
? ? ? ? ? ? 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ù):啟動就緒。
");
? ? 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, "無效賬號!");
? ? ? ? ? ? goto send_respond;
? ? ? ? }
? ? ? ? if (strcmp (req.name, acc.name)) {
? ? ? ? ? ? sprintf (res.error, "無效戶名!");
? ? ? ? ? ? goto send_respond;
? ? ? ? }
? ? ? ? if (strcmp (req.passwd, acc.passwd)) {
? ? ? ? ? ? sprintf (res.error, "密碼錯誤!");
? ? ? ? ? ? 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ù):啟動就緒。
");
? ? 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, "無效賬號!");
? ? ? ? ? ? goto send_respond;
? ? ? ? }
? ? ? ? if (strcmp (req.name, acc.name)) {
? ? ? ? ? ? sprintf (res.error, "無效戶名!");
? ? ? ? ? ? goto send_respond;
? ? ? ? }
? ? ? ? if (strcmp (req.passwd, acc.passwd)) {
? ? ? ? ? ? sprintf (res.error, "密碼錯誤!");
? ? ? ? ? ? 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ù):啟動就緒。
");
? ? 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, "無效賬號!");
? ? ? ? ? ? goto send_respond;
? ? ? ? }
? ? ? ? if (strcmp (req.name, acc.name)) {
? ? ? ? ? ? sprintf (res.error, "無效戶名!");
? ? ? ? ? ? goto send_respond;
? ? ? ? }
? ? ? ? if (strcmp (req.passwd, acc.passwd)) {
? ? ? ? ? ? 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;
}
//轉(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ù):啟動就緒。
");
? ? 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, "無效賬號!");
? ? ? ? ? ? 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, "密碼錯誤!");
? ? ? ? ? ? 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, "無效對方賬號!");
? ? ? ? ? ? goto send_respond;
? ? ? ? }
? ? ? ? if (strcmp (req.name[1], acc[1].name)) {
? ? ? ? ? ? sprintf (res.error, "無效對方戶名!");
? ? ? ? ? ? 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, "更新對方賬戶失??!");
? ? ? ? ? ? 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;
}
//封裝的庫(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;
}
//庫的聲明(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消息隊列在多進(jìn)程間通信的使用過程,在實(shí)際開發(fā)中應(yīng)用是非常廣泛的,十分建議初學(xué)Linux編程的工程師們?nèi)ゾ毩?xí)這套系統(tǒng),加深消息隊列在多進(jìn)程間通信的應(yīng)用,這將具有很大的益處。
電子發(fā)燒友App













評論