アナログプロセス通信


1,実験では、forkを2回呼び出して2つのサブプロセスを作成することが要求されており、そのうちの1つはサーバserverとして機能し、もう1つはクライアントclientとして機能し、オペレーティングシステムの内部プロセス間の通信をシミュレートする。クライアントがサーバメッセージタイプmtypeに10から1のメッセージを送信し、サービス端末がメッセージを受信し、タイプ1のメッセージを受信すると受信を停止する。2,プロセス間通信の主な関数:
/*  1   :         :MSGKEY           ,           ;0777|IPC_CREAT         :     id */
msgqid=msgget(MSGKEY,0777|IPC_CREAT);//      
/*  2   :       :msgqid,      id;&msg            ;1024              1024  , 1K;-10,                 10           ;0,               ,    。 */
msgrcv(msgqid,&msg,1024,-10,0);//    
/*  3   :       :msgqid,       id;&msg            ;1024           1024  , 1K;0,               ,    。 */
msgsnd(msgqid,&msg,1024,0);       //    
/*  4   :         :msgqid,           id;IPC_RMID           ; */
    msgctl(msgqid,IPC_RMID,0);
3コード実現
/*Name:shiyan4.c *Created on 2015-10-14 *Author:Wanglin *Function:       ,            */
#include<stdio.h>
#include<unistd.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
# include<string.h>
#define MSGKEY 75
struct msgform
{
    long mtype; //    
    char mtext[1024];//1k    
} msg;
int msgqid;//    id,        
int main()
{
    int p1,p2;
    p1=fork();//  server 
    if(!p1)
    {
        //[server ]
        msgqid=msgget(MSGKEY,0777|IPC_CREAT);// server       
        do
        {
            msgrcv(msgqid,&msg,1024,-10,0);//server     
            printf("i=%d server:received
"
,msg.mtype);// server msg.mtype=1000;// , 1000( 1-10 ) msgsnd(msgqid,&msg,1024,0); /* msg*/ } while(msg.mtype!=1); msgctl(msgqid,IPC_RMID,0);// } else { p2=fork();// lient if(!p2) { //[client ] int i; msgqid=msgget(MSGKEY,0777|IPC_CREAT);// MSGKEY ,client server for(i=10; i>=1; i--) { msg.mtype=i; msgsnd(msgqid,&msg,1024,0); // msgqid msg printf("i=%d client:send
"
,i); msgrcv(msgqid,&msg,1024,1000,0); // } } } /*wait(0) , */ wait(0);// wait(0);// return 0; }
4,コードをコンパイルして実行します。
[root@localhost os]# vim shiyan4_V3.c
[root@localhost os]# gcc shiyan4_V3.c
[root@localhost os]# ./a.out 
[root@localhost os]# i=10 server:received
i=10 client:send
i=9 server:received
i=9 client:send
i=8 server:received
i=8 client:send
i=7 server:received
i=7 client:send
i=6 server:received
i=6 client:send
i=5 server:received
i=5 client:send
i=4 server:received
i=4 client:send
i=3 server:received
i=3 client:send
i=2 server:received
i=2 client:send
i=1 server:received
i=1 client:send
その結果、serverとclient端末が交互に現れて、client側は全部で10回のメッセージを送りましたので、iは10から1までです。実験結果は予期していた効果とはちょっと違っています。まずclient:sentを表示してからserver:receivedを表示します。結果はこれと反対です。どう説明しますか?clientとserverは同時に実行する2つのプロセスで、もしロックをかけないならば、両者はいつでも相手のCPUを奪い取ることができて、この2つのプロセスのスケジュールは順序のスケジューラによって決まります。私達が書いたコードで決めたのではありません。最初にServerによってメッセージキューが作成され、メッセージキューが空であるため、clientからメッセージキューに最初のi=10のメッセージが送信されます。この時メッセージキューの中にメッセージがあります。serverはclientのcpuを奪い、メッセージキューのメッセージを受信します。そこで、serverはclientの前に先に「i=10 server:received」を出力します。5、注意事項(1)は、応答メッセージのmtypeを修正し、clientが送信するメッセージの種類と同じでないようにし、この例では1000に設定する。(2)server端でメッセージを受信する場合、msgrcvの4番目のパラメータの合理的な範囲(-999、-10)を直接の整数にすることに注意します。
 msgrcv(msgqid,&msg,1024,-10,0);//server     
(3)client端がServerの応答メッセージを受信する場合、msgrcvの4番目のパラメータは、応答メッセージのmtypeと同じである1000でなければなりません。
 msgrcv(msgqid,&msg,1024,1000,0);        //              
応答メッセージのmtypeを修正する役割は、これらの2つのメッセージを区別するために用いられる。一つはserver端の応答メッセージであり、メッセージタイプmtype=1000、二つはclient端がserver端に送信したメッセージであり、メッセージタイプ1<=mtype==10。server側はメッセージを受信する時、msgrcvの4番目のパラメータが0であると仮定して、メッセージキュー内の第1のメッセージを受信すると、それは先ほどclient側に戻った応答メッセージを受信することができます。これは不合理です。応答メッセージはclient側でのみ受信することを望みます。msgrcvを設定する第3のパラメータは−10であり、メッセージタイプが10以下のメッセージしか受信できないことを示し、応答メッセージのメッセージタイプが1000に設定されているので、serverは応答メッセージを間違って受信しない。client側で応答メッセージを受信する場合、msgrcvを指定する4番目のパラメータは1000であり、client側は自分がserverに送信したメッセージを受信せず、エラーを避けるために応答メッセージだけを受信することを保証している。(4)プログラムが終了したら、クリアと削除を覚えてください。削除しないとメッセージキューがメモリに保存され、次回のプログラムの実行に影響を与える可能性があります。
msgctl(msgqid,IPC_RMID,0);//         
6,まだ解決しなければならない問題のこのプログラムはまだ多くの開拓できるところがあります。(1)プロセスを正常に終了させるにはどうすればいいですか?プログラムの実行が終わった後、自動的にshellに戻りませんでした。割り込み(例えばctrl+C)でshellに戻ります。どうやってshellに自動的に戻りますか?
...
i=1 server:received
i=1 client:send
//        shell  [root@localhost os],      
(2)clientエンドsentをどうやって実現しますか?上で分析したことがありますが、この二つのプロセスはいつでもお互いに中断します。もし必ずclient:sendを前にして、server:receivedを後にしたら、どうやって実現しますか?(3)2つのメッセージキューを使用しますか?(4)実際には、1つのサーバは、多くのクライアントにサービスを提供していますが、どのように複数のclientをシミュレートして送信しますか?