大家好,我是ST。
今天主要聊一聊,如何使用Linux系統(tǒng)下的msg實(shí)現(xiàn)銀行終端系統(tǒng)的模擬及運(yùn)行。
第一:msg基本簡介
????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)語句可以定義一個(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ù)庫可以將每一位用戶的信息都保存到數(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ù):啟動(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ù):啟動(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ù):啟動(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ù):啟動(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ù):啟動(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ù):啟動(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;
}
//封裝的庫(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消息隊(duì)列在多進(jìn)程間通信的使用過程,在實(shí)際開發(fā)中應(yīng)用是非常廣泛的,十分建議初學(xué)Linux編程的工程師們?nèi)ゾ毩?xí)這套系統(tǒng),加深消息隊(duì)列在多進(jìn)程間通信的應(yīng)用,這將具有很大的益處。
電子發(fā)燒友App






















評(píng)論