システムプログラミング10


第10課


プロセス間通信


スレッドは1つのプロセスで共存するため、グローバル変数を設定するには特別な共有メカニズムは必要ありません.
ただし,プロセス間では独立したアドレスとリソースが使用されるため,共有機能が必要である,これがIPCである.
プロセス間通信と同期
目的:転送、共有、イベント転送、リソース共有と同期、制御
どうしよう.
2つのモデルがあります.
  • Message Passing

  • プロセス間で直接転送できないため、ユーザー層のKernelを使用してMsgを転送します.
  • メカニズム
  • Message Queue
  • Pipes
  • Mailboxes
  • Sockets
  • 共有メモリ:特定のメモリ(共有)を定義する

  • IPC例

  • 同期用Primitives
    Ex )
    Semaphore->Thread間の同期.プロセッサ間の同期はIPC
    Debugging
    Event Notification - UNIX signals

  • 2種類のPrimitives
  • Send(destination, msg) or Send((msg))
  • Receive(source msg) or receive(msg)

  • サイズは変えても固定してもいいです.
  • Message Passing


    Send <----------> Receive
  • 通信リンクを作成します.
  • を送信、受信するメール
  • を生成する.
    に道を教える

  • Direct OR Indirect

  • Symmetric OR Asymmetric

  • Automatic buffering OR Explicit Buffering
    :メッセージに必要な内容をバッファに入れ、バッファサイズを管理する

  • Send-by-Copy OR Send-by-Reference
    :メモリが大きい場合は、時間がかかります.このとき、「オンデマンドリファレンス」(C言語のPointerのように)

  • Fixed OR Variable message size
  • Direct Communication & Indirect Communication


    Direct Communication
    に指名
    Q->P仮定,Send(P,messge),Receive(Q,messge)
    条件
  • の両方のプロセスはアクティブでなければなりません.
  • 通信リンクは自動的に作成(直接命名)された
  • である.
    相手の
  • プロセスIDを正確に理解する必要があります.
  • Indirect Communication
    :直接点呼しません.
    Q---> mailBox ---> P
    mailBoxが存在する->ユニークなIDが必要です.つまり、プロセスごとに1つが必要です.
    directとの違いは?
  • Qは、Pの準備ができているかどうかにかかわらず送信できます.
  • は、他のプロセスと容易に共有できます.

  • もし同時に2つの受信プロセスがあれば?

    解決策

  • メールボックスを有効にするには、2つのプロセスのみを定義します.(P--->Q, P---.R)

  • 同時アクセスは許可されていません.
    -->プロセス間で同期が必要(lock...)
  • Symmetric Communication


    Symmetric = blocking = synchronous
    Sender&Receiverをブロック状態にします.
    :応答が受信されるまで送信後にブロック
    特長
    Function Callに似ています

    main関数の進行中にfoo関数を呼び出すと、foo関数が終了するまでmain関数は停止します.

    Non-Blocking (asynchronous)


    意味:Senderから送信されたタスクを完了し、動作を継続します.
    差異

    Message Queue



    Send_message.c
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define MSGSZ 128
    
    typedef struct msgbuf
    {
        long mytype;
        char mtext[MSGSZ];
    } message_buf;
    
    int main(int argc, char const *argv[])
    {
        int msgId;
        int msgflag = IPC_CREAT | 0666;
        key_t key;
        message_buf sbuf;
        size_t buf_length;
    
        key = 1234;
    
        if ((msgId = msgget(key, msgflag)) < 0)
        {
            perror("msgget");
            exit(1);
        }
    
        sbuf.mytype = 1;
    
        (void)fprintf(stderr, "msgget : msgget succeeded: msgid = %d\n", msgId);
    
        (void)strcpy(sbuf.mtext, "Did you get this?");
    
        (void)fprintf(stderr, "msggget : msgget succeededd : msgid = %d\n", msgId);
    
        buf_length = strlen(sbuf.mtext) + 1;
    
        if (msgsnd(msgId, &sbuf, buf_length, IPC_NOWAIT) < 0)
        {
            printf("%d, %ld, %s, %zu \n", msgId, sbuf.mytype, sbuf.mtext, buf_length);
    
            perror("msgsnd");
            exit(1);
        }
        else
        {
            printf("Message : \"%s\" Send\n", sbuf.mtext);
        }
    
        exit(0);
    
        return 0;
    }
    recv_msg.c
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    #define MSGSZ 128
    
    typedef struct msgbuf
    {
        long mytype;
        char mtext[MSGSZ];
    
    } message_buf;
    
    int main(int argc, char const *argv[])
    {
        int msgId;
        key_t key;
        message_buf sbuf;
    
        key = 1234;
    
        // if ((msgId = msgget(key, msgflag)) < 0)
        // {
        //     perrpr("msgget");
        //     exit(1);
        // }
    
        if (msgrcv(msgId, &sbuf, MSGSZ, 1, 0) < 0)
        {
            perror("msgrcv");
            exit(1);
        }
    
        printf("%s\n", sbuf.mtext);
        exit(0);
    
        return 0;
    }

    Pipe

  • FIFO buffer
  • ファイルI/O外観は
  • と同じ
  • Asynchronous
  • 双方向Arrayg形状
  • read-write pipe
  • 0番idx:read,1番idx:write

  • pipe.c
    #include <unistd.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <string.h>
    
    char *message = "Do u see this msg ?";
    
    int main(int argc, char const *argv[])
    {
        char buf[1024];
        int fd[2];
        pipe(fd);
    
        if (fork() != 0)
        {
            write(fd[1], message, strlen(message) + 1);
        }
        else
        {
            read(fd[0], buf, 1024);
            printf("Got this from Parent! : &s\n", buf);
        }
        return 0;
    }
  • Fork():同じサブプロセスを作成する