Linux进程通信(无名管道,有名管道,共享内存)的实现

   Linux进程的通信有很多种方式,比如无名管道,有名管道,共享内存,Android进程通信采用的确是Binder机制~~~

   在学习进程通信之前先学习一下System,Fork,Execive的机制,System调用的是另一个进程跟自己毫无关系 用的比较少。Fork创建的是父子进程,父进程的内存会被复制到

字进程的内存空间区别就是PID的不同。Execive调用的进程就会保留内存空间但是执行的是调用程序的代码。

   首先看一下这三种创建进程的方法区别:

  Execive:

  

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>



int main(void)
{

  printf("start\n");
  char* args[] = {"/bin/ls","-l",NULL};
  execve("/bin/ls",args,NULL);
  printf("end\n");
  return EXIT_SUCCESS;
}
执行到execive是内存空间会被/bin/ls占据,后面的打印语句就会被取消没有打印出来

重点看一下Fork机制:

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>



int main(int arg,char*args[])
{
  printf("begin\n");
  pid_t child = fork();
  if(child == -1)
  {
    return -1;
  }
  if(child == 0)
  {
    printf("is child\n");

    printf("child  pid = %d\n",getpid());


  }else
  {
     printf("is parent\n");

     printf("parent i pid = %d\n",getpid());


  }
  printf("end\n");

  return EXIT_SUCCESS;
}
~                   



#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/wait.h>



int main(int arg,char*args[])
{

  int status;
  pid_t child = fork();
  if(child == -1)
  {
    return -1;
  }
  if(child == 0)
  {
    printf("child start\n");
    sleep(5);
    printf("child end\n");
    return 100;

  }else
  {
     printf("parent start\n");
     wait(&status);
     printf("status = %d\n",WEXITSTATUS(status));
     printf("parent end");


  }
  printf("end\n");

  return EXIT_SUCCESS;
}
~                  
父进程必须使用wait等待子进程结束掉才能关闭掉,通过status获得返回值,如果子进程死掉,父进程活着,子进程就会变成僵尸进程占据资源


nt main(int arg,char*args[])
{

  int status;
  pid_t child = fork();
  if(child == -1)
  {
    return -1;
  }
  if(child == 0)
  {
    exit(0);

  }else
  {
     printf("parent start\n");
     sleep(30);
     printf("parent end");


  }
  printf("end\n");

  return EXIT_SUCCESS;
}
~                                                                                                                                   
~                                                                                                                                   
~                                                                                                                                   
~                                  
这个时候通过ps aux可以看到子进程已经僵死



#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/wait.h>

int main(int arg,char*args[])
{

  close(STDOUT_FILENO);
  open("/dev/pts/1",O_WRONLY);
  pid_t child = fork();
  if(child == -1)
  {
    return -1;
  }
  if(child == 0)
  {
    char* args[] = {"/bin/ls","-l",NULL};
    execve("/bin/ls",args,NULL);

  }else
  {
    exit(0);

  }
  printf("end\n");

  return EXIT_SUCCESS;
}
~                                                                                                                                   
~                                                                                                                                   
~                                                                                                                                   
~                                                                                                                                   
~                                                                                                                                   
~                                                                                                                                   
~                                           

这个案例会发现父子进程共享文件描述符,然后execve打印在控制台/dev/pts/1上


OK 理解了父子进程 进程创建的方式开始讲一下进程通信:

管道是管道文件,无名管道限于父子进程之间的通信,有名管道是任何两个进程的通信,共享内存也是。

无名管道通信如下:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int arg,char* args[])
{
  int fd[2];
  char message[100];
  int len;
  pipe(fd);
  memset(message,0,sizeof(message));
  int pid = fork();
  if(pid == 0)
  {
    close(fd[1]);
    while((len = read(fd[0],message,sizeof(message))) > 0 )
    {
       write(STDOUT_FILENO,message,len);
    }
    close(fd[0]);

  }else
  {
    close(fd[0]);
    strcpy(message,"shaozhongqi come from nanjing");
    write(fd[1],message,sizeof(message));
    close(fd[1]);
    waitpid(pid,NULL,0);
  }

  return EXIT_SUCCESS;
}
通过pipe()方法创建无名管道,父进程写数据,子进程读数据直到管道文件被关闭

有名管道需要通过命令mkfifo创建

案例如下:

#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int arg,char* args[])
{
  char buf[100];
  int len;
  int fd = open("testfifo",O_RDONLY);
  memset(buf,0,sizeof(buf));
  while((len = read(fd,buf,sizeof(buf))) > 0)
  {
     write(STDOUT_FILENO,buf,strlen(buf));
     memset(buf,0,sizeof(buf));
  }
  return EXIT_SUCCESS;
}
打开管道文件testfifo,然后从管道读数据

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


int main(int arg,char* args[])
{

  char buf[100];
  int fd = open("testfifo",O_WRONLY);
  memset(buf,0,sizeof(buf));
  while(1)
  {
    read(STDIN_FILENO,buf,sizeof(buf));
    if(buf[0] == '0')
    {
      close(fd);
      break;
    }else
    {
      write(fd,buf,strlen(buf));
      memset(buf,0,sizeof(buf));
    }

  }

  return EXIT_SUCCESS;
}
~                                                                                                                                   
~                                                                                                                                   
~                                                                                                                                   
~                  
打开管道文件写数据  直到这完成了单向的管道读写数据


下面将一些共享内存 首先通过

#include <sys/types.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int main(int arg,char* args[])
{

  int shmid = shmget(IPC_PRIVATE,1024,0666);
  if(shmid < 0)
  {
    printf("failure\n");
  }else
  {
    printf("id:%d\n",shmid);
  }
  return EXIT_SUCCESS;
}
             

然后通过命令ipcs -m 查看共享内存的信息 返回共享内存的id



下面就是进程在自己内存开辟一块内存与共享内存进行关联,当进程在自己的内存中读写数据会同步到共享内存中(进程是不能直接操作共享内存的)

、include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int main(int arg,char* args[])
{
  char* shmbuf;
  int shmid = 0;
  if(arg < 2)
  {
    return -1;
  }

  shmid = atoi(args[1]);
  shmbuf = shmat(shmid,0,0);
  if(atoi(args[2]) == 1)
  {
     //read
     printf("%s\n",shmbuf);

  }else if(atoi(args[2]) == 2)
  {
     //write
     scanf("%s\n",shmbuf);

  }
  shmdt(shmbuf);
  return EXIT_SUCCESS;
}
~                                                                                                                                                            
~      

Ok  基本学习到此










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值