【linux下c語言服務器開發系列3】進程間通信

    上個博文說道,信號是在進程間通信的的一種方式。例如子進程執行結束後,向父進程發送sigchld信號,父進程就經過捕獲這個信號,就能夠對子進程的資源進行回收,避免其成爲殭屍進程。 git

    進程間通訊的另一種方式是管道,主要是在父子進程間。父進程經過創立一個管道,fork()出子進程後,子進程繼承父進程的管道,從而,父子進程就造成了管道的兩端,從而能夠靠這兩端,進行父子進程之間的通訊。 服務器

建立管道 dom

    建立管道的方法主要有兩種,一種是pipe函數,能夠man一下,解釋很清晰的;另一種是socketpair函數。前者建立的管道是半雙工的,後者的是全雙工的。 socket

    下面是一個父子進程間通信的一個小例子。鏈接見http://git.oschina.net/mengqingxi89/codelittle/blob/master/codes/echoserver/ipc_shared_talker.cpp 函數

例子中有個小問題沒有解決,就是父進程往管道里寫數據,若是寫的過快的話,致使子進程沒有接到。因此我讓父進程寫一句,sleep(1),而後再寫。這樣,子進程就都收到了。我想,多是管道沒有存儲的功能?多寫的話,就寫不進去了。不知道。 .net

進程間通信的另外一個方式是共享內存。這個,我要在下面的聊天室程序裏介紹,這裏就沒介紹了。 code

#include"head.h"
#define MAX_USER 1024
#define MAX_PROCESS 65535
#define BUF_SIZE 1024 

typedef struct user
{
        int conn;
        int stop;
        sockaddr_in client_addr;
        char bufread[BUF_SIZE];
        char bufwrite[BUF_SIZE];
        int pipefd[2];   //用來創建管道,一端是父進程,一端是子進程。
} user;


typedef struct subprocessData
{
        user* u;
        pid_t pid;
        pid_t ppid;

}subprocessData;


subprocessData subprocess[MAX_PROCESS];


/*子進程從父進程那裏讀取內容*/
int dowork_comm_with_father(user curuser)
{       

        curuser.stop=0;
        //子進程關閉寫端
        close(curuser.pipefd[1]);

        setnonblock(curuser.pipefd[0]);
        while(!curuser.stop )
        {

            int readn=read(curuser.pipefd[0],curuser.bufread,BUF_SIZE);
            if( (readn<0) && (errno!=EAGAIN))
            {
                    printf("a\n");
                    printf("read fail, client ");
                    close(curuser.pipefd[0]);
                    curuser.stop=1;
                    
            }
            else if (readn==0)
            {
                    printf("father close the pipe\n");
                    close(curuser.pipefd[0]);
                    curuser.stop=1;
            }

            else if (readn>0)
            {
                    printf("pid= %d\n",getpid());
                    curuser.bufread[readn]='\0';
                    printf("read from the father\n");
                    printf("%s\n",curuser.bufread);
                    int writen=write(1,curuser.bufwrite,sizeof(curuser.bufwrite));
                    
                    memset(curuser.bufread,0,sizeof(curuser.bufread));
            }


        }
}
        int main(int argc, char **argv)
        {
                printf("start server...\n");


        /*服務器服務啓動,等待客戶端的連接的到來*/
            int run_flag=1;

            user users[MAX_USER];
            int user_number=0;
            /*這個pipe函數是簡單的建立管道的版本,他建立的管道,pipefd[0]只能讀,pipefd[1]只能寫*/
            int fdret=pipe(users[user_number].pipefd);
            
            assert(fdret>=0);

            pid_t pid=fork();
            if(pid<0)
            {
                    printf("fork error\n");
                    exit(0);
            }
            else if (pid==0)
            {

                    dowork_comm_with_father(users[user_number]);
            }

            /*parent process*/
            else
            {
                    /*在父進程中向子進程寫一些random內容*/

                    printf("pid=%d in parent\n",pid);
                    subprocess[pid].u=&users[user_number];
                    close(users[user_number].conn);
                    //父進程關閉管道的讀端,只往子進程寫內容
                    close(users[user_number].pipefd[0]);

                    int write_times=5;
                    for(int i=0;i<write_times;i++)
                    {
                            
                            char buf[100]="hello from parent at time ";
                            char bufwrite[100];
                            sprintf(bufwrite,"%s",buf);
                            sprintf(bufwrite," %d\n",time(NULL));
                            write(users[user_number].pipefd[1],bufwrite,sizeof(bufwrite));

                            sleep(1);
                    }
                    printf("parent write over\n");

                    int stat_loc;
                    /*若是想要多個進程共同服務的話,就不能在這裏阻塞的等待,能夠經過sigchld信號進行捕獲,見信號handler*/
                 //   wait((int *)&stat_loc);
                    printf("parent, finished wait\n");
                   // sleep(3);
            }

        
}
相關文章
相關標籤/搜索