IPS 进程通信

linux系统下每个进程都有自己独立的内存空间,但实际应用却需要它们互相的通信去完成某项复杂的任务,这与面向对象程序的设计思想:高内聚,低耦合的思想一脉相承。linux下进程通信的方式:1.管道 2.有名管道(FIFO) 3.消息队列 4.共享内存 5.UNIX套接字。管道主要用于父子进程中,而有名管道是用于无亲缘关系的进程中。管道在linux命令很常见,如 who | sort | lp ,who的进程的输出是sort进程的输入,sort进程的输出又是lp进程的输入。共享内存是最快的一种通信方式。

1.管道(pipe)

父子进程通过双向管道通信
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#define MAXFIFOSIZE  1024

/*通用ips通信结构体*/
typedef struct stIPSMsg
{
    char   cFrameType;
    long   lDataLength;
    char   acData[MAXFIFOSIZE];
}ST_IPS_MSG;

void *WriteTask( void *args)
{
  int iWriteFd = *(int *)args;
  char acPipeBuff[MAXFIFOSIZE];
  int iWriteLen;
  sprintf(acPipeBuff, "ok, client  seems work ! Continue to relax.");
  int len = strlen( acPipeBuff);
  ST_IPS_MSG * stIPSMsg = (ST_IPS_MSG * ) malloc( sizeof(ST_IPS_MSG ));
  //stIPSMsg->acData = (char *) malloc(len);
  stIPSMsg->cFrameType = 0;
  stIPSMsg->lDataLength = len;
  memcpy(stIPSMsg->acData, acPipeBuff, len);
  while( ( iWriteLen = write( iWriteFd, (void*)stIPSMsg, sizeof(ST_IPS_MSG )+len ) ) > 0)
  {
      sleep(1);
  }
  //free(stIPSMsg->acData);
  free(stIPSMsg);
}

int main(int argc, char *argv[])
{
    int pipe_one[2], pipe_two[2];
    int iRecvLen;
    char acPipeBuff[MAXFIFOSIZE];
    pid_t    pid;
    pthread_t      WritePthreadId;

   pipe(pipe_one);
   pipe(pipe_two);
    if( (pid = fork() ) < 0)
      {
          printf("Fork LNSIP Process Error . \r\n"); 
      }
    if (0 == pid)
      {
             close(pipe_one[1]);
         close(pipe_two[0]);
      char acReadFd[5], acWriteFd[5];
      sprintf(acReadFd, "%d", pipe_one[0]);
      sprintf(acWriteFd,"%d",pipe_two[1]);
          execl("./pipeclient", "pipeclient",acReadFd, acWriteFd, NULL);
      }
    else
      {
          close(pipe_one[0]);
      close(pipe_two[1]);
  }

    pthread_attr_t stAttr;
    ( void )pthread_attr_init( &stAttr );
    ( void )pthread_attr_setdetachstate( &stAttr , PTHREAD_CREATE_DETACHED );
    ( void )pthread_attr_setstacksize( &stAttr , 500*1024 );
    int bPthreadCreateWrong = (pthread_create(&WritePthreadId, &stAttr
        , (void * (* )(void *) )WriteTask, (void*)&pipe_one[1]) != 0);
    if(bPthreadCreateWrong)
    {
        printf(  "Call Init write task failed.\r\n");
        return NULL;
    }

    while( ( iRecvLen = read( pipe_two[0], acPipeBuff, sizeof(ST_IPS_MSG )+MAXFIFOSIZE ) ) > 0)
        {
             ST_IPS_MSG * stIPSMsg = (ST_IPS_MSG * )acPipeBuff;
            printf("Server Recive Content : %s Length: %d \r\n", stIPSMsg->acData, stIPSMsg->lDataLength);
        }
}

管道两个文件描述符通过参数传给子程序

子进程程序实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
int main(int argc, char *argv[])
{
    int iReadFd, iWriteFd;
    int iRecvLen;
    char acPipeBuff[MAXFIFOSIZE];
  pthread_t      WritePthreadId;

   iReadFd = atoi(argv[1]);
   iWriteFd = atoi(argv[2]);

    pthread_attr_t stAttr;
    ( void )pthread_attr_init( &stAttr );
    ( void )pthread_attr_setdetachstate( &stAttr , PTHREAD_CREATE_DETACHED );
    ( void )pthread_attr_setstacksize( &stAttr , 500*1024 );
    char bPthreadCreateWrong = (pthread_create(&WritePthreadId, &stAttr
        , (void * (* )(void *) )WriteTask, (void*)&iWriteFd) != 0);
    if(bPthreadCreateWrong)
    {
        printf( "Call Init write task failed.\r\n");
        return NULL;
    }

    while( ( iRecvLen = read( iReadFd, acPipeBuff, sizeof(ST_IPS_MSG )+MAXFIFOSIZE ) ) > 0)
        {
            ST_IPS_MSG * stIPSMsg = (ST_IPS_MSG * )acPipeBuff;
            printf("Client Recive Content : %s Length: %d \r\n", stIPSMsg->acData, stIPSMsg->lDataLength);
        }
}

2.有名管道(FIFO)

父子进程通过有名管道FIFO通信
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#define FIFO_ONE "/tmp/fifo_one"
#define FIFO_TWO "/tmp/fifo_two"
#define FILE_MODE        (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
#define MAXFIFOSIZE  1024
void handler(int sig)
{

  unlink(FIFO_ONE);
  unlink(FIFO_TWO);
  printf("Catch signal Terminate the father process signal: %d .\r\n", sig);
}

int main(int argc, char *argv[])
{
    int iReadFd, iWriteFd;
    int iRecvLen;
    char acFifoBuff[MAXFIFOSIZE];
    pid_t    pid;
    pthread_t      WritePthreadId;
    struct sigaction sa;

    sigemptyset(&sa.sa_mask);
  sa.sa_flags = 0;
  sa.sa_handler = handler;
  if (sigaction(SIGINT, &sa, NULL) == -1 ||
          sigaction(SIGQUIT, &sa, NULL) == -1 ||
          sigaction(SIGTERM, &sa, NULL) == -1)
  {
      printf( "Error: FATAL: unable to create signal handlers\n");
  }

    if((mkfifo(FIFO_ONE, FILE_MODE)<0 ) && (errno != EEXIST))
      printf( " Can't Create FIFO %s.\r\n", FIFO_ONE);
    if((mkfifo(FIFO_TWO, FILE_MODE)<0) &&(errno != EEXIST))
      printf( " Can't Create FIFO %s.\r\n",FIFO_TWO);  
    if( (pid = fork() ) < 0)
      {
          printf("Fork LNSIP Process Error . \r\n"); 
      }
    if (0 == pid)
      {
          execl("./fifoclient", "fifoclient", NULL);
      }
    else
      {
          if(( iWriteFd = open(FIFO_ONE, O_WRONLY, 0)) < 0)
              printf(" Can't Open FIFO %s.\r\n", FIFO_ONE);    
      if ((iReadFd  = open(FIFO_TWO, O_RDONLY, 0) )< 0)
              printf(" Can't Open FIFO %s.\r\n", FIFO_TWO);    
  }

    pthread_attr_t stAttr;
    ( void )pthread_attr_init( &stAttr );
    ( void )pthread_attr_setdetachstate( &stAttr , PTHREAD_CREATE_DETACHED );
    ( void )pthread_attr_setstacksize( &stAttr , 500*1024 );
    int bPthreadCreateWrong = (pthread_create(&WritePthreadId, &stAttr
        , (void * (* )(void *) )WriteTask, (void*)&iWriteFd) != 0);
    if(bPthreadCreateWrong)
    {
        printf(  "Call Init write task failed.\r\n");
        return NULL;
    }

    while( ( iRecvLen = read( iReadFd, acFifoBuff, sizeof(ST_IPS_MSG )+MAXFIFOSIZE ) ) > 0)
        {
             ST_IPS_MSG * stIPSMsg = (ST_IPS_MSG * )acFifoBuff;
            printf("Server Recive Content : %s Length: %d \r\n", stIPSMsg->acData, stIPSMsg->lDataLength);
        }
     close(iReadFd);
     close(iWriteFd);
     unlink(FIFO_ONE);
     unlink(FIFO_TWO);
}

子进程只要打开同样的FIFO文件,得到其文件描述符,就可以与父进程通信

子进程程序实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
int main(int argc, char *argv[])
{
    int iReadFd, iWriteFd;
    int iRecvLen;
    char acFifoBuff[MAXFIFOSIZE];
    pthread_t      WritePthreadId;

    if(( iReadFd = open(FIFO_ONE, O_RDONLY, 0)) < 0)
        printf( " Can't Open FIFO %s.\r\n", FIFO_ONE); 
    if ((iWriteFd  = open(FIFO_TWO, O_WRONLY, 0)) < 0)
        printf(" Can't Open FIFO %s.\r\n", FIFO_TWO);

    pthread_attr_t stAttr;
    ( void )pthread_attr_init( &stAttr );
    ( void )pthread_attr_setdetachstate( &stAttr , PTHREAD_CREATE_DETACHED );
    ( void )pthread_attr_setstacksize( &stAttr , 500*1024 );
    char bPthreadCreateWrong = (pthread_create(&WritePthreadId, &stAttr
        , (void * (* )(void *) )WriteTask, (void*)&iWriteFd) != 0);
    if(bPthreadCreateWrong)
    {
        printf( "Call Init write task failed.\r\n");
        return NULL;
    }

    while( ( iRecvLen = read( iReadFd, acFifoBuff, sizeof(ST_IPS_MSG )+MAXFIFOSIZE ) ) > 0)
        {
            ST_IPS_MSG * stIPSMsg = (ST_IPS_MSG * )acFifoBuff;
            printf("Client Recive Content : %s Length: %d \r\n", stIPSMsg->acData, stIPSMsg->lDataLength);
        }
     close(iReadFd);
     close(iWriteFd);
     unlink(FIFO_ONE);
     unlink(FIFO_TWO);
}

3.共享内存(mmap)

父子进程通过共享内存mmap通信
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/sem.h>
#include <semaphore.h>
#define MAXFIFOSIZE  1024

#define MAXLOOP        1024
#define FileName         "/tmp/tempmap"
#define FILE_MODE        (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

 struct st_Shared
{
   sem_t mutex;
   int count;
}st_Shared;

int main(int argc, char *argv[])
{
    int fd, i;
    struct st_Shared *pShared;

    fd = open(FileName, O_RDWR | O_CREAT, FILE_MODE);
    write(fd, &st_Shared,  sizeof(struct st_Shared) );
    pShared =(struct st_Shared*)mmap(NULL, sizeof(struct st_Shared), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    sem_init(&pShared->mutex, 1, 1);
    setbuf(stdout, NULL);
    if( fork() == 0)
      {
          for(i = 0; i< MAXLOOP; i++ )
          {
              sem_wait(&pShared->mutex);
          printf("child process count: %d .\r\n", pShared->count++);
          sleep(1);
          sem_post(&pShared->mutex);
          }
      }
   for(i = 0; i < MAXLOOP; i++)
      {
         sem_wait(&pShared->mutex);
     printf("father process count: %d .\r\n", pShared->count++);
     sleep(1);
     sem_post(&pShared->mutex);
      }
}

Comments