[应用相关]

进程间通讯 小总结

[复制链接]
975|36
手机看帖
扫描二维码
随时随地手机跟帖
hanzhen654|  楼主 | 2019-3-25 13:20 | 显示全部楼层 |阅读模式
为什么进程间需要通讯?
01.数据传输
02.资源共享
03.通知事件
04.进程控制

使用特权

评论回复
hanzhen654|  楼主 | 2019-3-25 13:20 | 显示全部楼层
linux进程间的通讯方式
01.管道(pipe)和有名管道(FIFO)
02.信号(signal)
03.消息队列
04.共享内存
05.信号量
06.套接字(socket)

使用特权

评论回复
hanzhen654|  楼主 | 2019-3-25 13:20 | 显示全部楼层
管道通讯
管道是单向的、先进先出的,它把一个进程的输出和一个进程的输入连接在一起。一个进程(写进程)在管道的尾部写入数据,另一个进程(读进程)从管道的头部读出数据。

使用特权

评论回复
hanzhen654|  楼主 | 2019-3-25 13:21 | 显示全部楼层
管道创建
   管道包括无名管道和命名管道两种,前者用于父进程和子进程的通讯,后者可用于运行与同一体系的两个进程间的通讯。
   无名管道由pipe() 函数创建,  int pipe(int filedis[2]); 当一个管道建立时,它会创建两个文件描述符:filedis[0]用于读管道,filedis[1]用于写管道。

使用特权

评论回复
hanzhen654|  楼主 | 2019-3-25 13:21 | 显示全部楼层
管道关闭
   关闭管道只需将两个文件描述符关闭,可以使用普通的close函数逐个关闭。

使用特权

评论回复
hanzhen654|  楼主 | 2019-3-25 13:22 | 显示全部楼层
无名管道通讯实例
#include<unistd.h>
#include<errno.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
int main()
{
  int pipe_fd[2];
  pid_t  pid;
  char buf_r[100];
  char* p_wbuf;
  int r_num;
  memset(buf_r,0,sizeof(buf_r));
  if(pipe(pipe_fd)<0)
  {
    printf("pipe creat fail\n");
    return -1;
  }
  if((pid=fork())==0)
  {
     close(pipe_fd[1]);
     sleep(2);
     if((r_num=read(pipe_fd[0],buf_r,100))>0)
     {
         printf("%d numbers read from the pipe is %s\n",r_num,buf_r);
     }
    close(pipe_fd[0]);
    exit(0);
  }
  else if(pid>0)
  {
    close(pipe_fd[0]);
    if(write(pipe_fd[1],"hello",5)!=-1)
         printf("parent write1 hello!\n");
    if(write(pipe_fd[1],"pipe",5)!=-1)
         printf("parent write2 pipe!\n");
    close(pipe_fd[1]);
    sleep(3);
    waitpid(pid,NULL,0);
    exit(0);      
   }
}


使用特权

评论回复
hanzhen654|  楼主 | 2019-3-25 13:26 | 显示全部楼层
输出结果如下:
287065c98666be5a52.png

使用特权

评论回复
hanzhen654|  楼主 | 2019-3-25 13:26 | 显示全部楼层
命名管道创建
#include<sys/types.h>
#include<sys/stat.h>
int mkfifo(const char* pathname, mode_t mode)
pathname: FIFO文件名   mode:属性
一旦创建了一个FIFO,就可以用open打开它,一般的文件访问函数(close、 read、 write等)都可用于FIFO。
当打开FIFO时,非阻塞标志(O_NONBLOCK)将对以后的读写产生如下影响:
1.没有使用O_NONBLOCK:访问要求无法满足时进程将阻塞。如试图读取空的FIFO,将导致进程阻塞。
使用O_NONBLOCK:访问要求无法满足时进程不阻塞,立刻出错返回。

使用特权

评论回复
hanzhen654|  楼主 | 2019-3-25 13:27 | 显示全部楼层
FIFO实例: fifo_write.c
fifo_read.c
#include<sys/types.h>
#include<sys/stat.h>
#include<errno.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define FIFO  "/home/lm/myfifo"
void main()
{
     char  buf_r[100];
     int fd;
     int nread;
     
     if((mkfifo(FIFO,O_CREAT|O_EXCL)<0)&&(errno!=EEXIST))
         printf("cannot creat fifoserver\n");
     printf("prepareing for reading bytes....\n");
     memset(buf_r,0,sizeof(buf_r));
     
     fd=open(FIFO,O_RDONLY|O_NONBLOCK,0);
     if(fd==-1)
     {
         perror("open");
         exit(1);
     }
     while(1)
    {
      memset(buf_r,0,sizeof(buf_r));
      if((nread=read(fd,buf_r,100))==-1)
      {
          if(errno==EAGAIN)
               printf("no data yet\n");
      }
      printf("read %s from FIFO\n",buf_r);
      sleep(1);
    }
   pause();
   unlink(FIFO);
}


使用特权

评论回复
hanzhen654|  楼主 | 2019-3-25 13:28 | 显示全部楼层
fifo_write .c
#include<sys/types.h>
#include<sys/stat.h>
#include<errno.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define FIFO_SERVER  "/home/lm/myfifo"
main(int argc,char** argv)
{
     char  w_buf[100];
     int fd;
     int nwrite;
     fd=open(FIFO_SERVER,O_WRONLY|O_NONBLOCK,0);
     if(argc==1)
     {
         printf("please send something\n");
         exit(-1);
     }
    strcpy(w_buf,argv[1]);
     if((nwrite=write(fd,w_buf,100))==-1)
      {
          if(errno==EAGAIN)
          printf("the FIFO has not been read yet,please try later\n");
      }
      else
      printf("write %s to the FIFO\n",w_buf);   
}


使用特权

评论回复
hanzhen654|  楼主 | 2019-3-25 13:28 | 显示全部楼层
信号通信
产生信号的条件:
01. 用户按某些按键。
02. 硬件异常,产生信号。
03. 可以使用kill函数将信号发送给另一个进程。
04. 用户可以使用kill命令将信号发送给其它进程

使用特权

评论回复
hanzhen654|  楼主 | 2019-3-25 13:29 | 显示全部楼层
几个常见的信号:
SIGHUP:从终端上发出的结束信号。
SIGINT:来自键盘中的中断信号。
SIGKILL:该信号结束接收信号进程。
SIGTERM:kill命令发出的信号。
SIGSTOP:来自键盘或者调试程序的停止执行信号。

使用特权

评论回复
hanzhen654|  楼主 | 2019-3-25 13:29 | 显示全部楼层
信号处理:
1.忽略次信号,大多数信号都按此种方式进行,有两种信号不能忽略:SIGKILL 和SIGSTOP,这两种信号向超级用户提供了一种终止或者停止进程的方法。
2.执行用户希望的动作。
   通知内核在某种信号发生时,调用一个用户函数。在用户函数中,执行用户希望的处理。
3.执行系统默认动作。
   对于多数信号,系统默认的动作是终止该进程。

使用特权

评论回复
hanzhen654|  楼主 | 2019-3-25 13:36 | 显示全部楼层
信号发送:
发送函数主要有 Kill 和 raise
区别:Kill既可以向自身发送信号,也可以向其他进程发送信号。与Kill函数不同的是,raise函数是向进程自身发送信号。
#include<sys/types.h>
#include<signal.h>
int kill (pid_t pid,int signo)
int raise (int signal)

使用特权

评论回复
hanzhen654|  楼主 | 2019-3-25 13:36 | 显示全部楼层
Alarm函数
该函数可以设置一个时间值(闹钟时间),到设置的时间到了,将会产生SIGNAL信号。如果不捕捉此信号,则默认动作是终止该进程。
#include<unistd.h>
unsigned int alarm(unsigned int seconds)
Seconds: 经过指定秒后将会产生信号。

使用特权

评论回复
frfgfvfd| | 2019-3-25 17:09 | 显示全部楼层
学习下!很不错的分享帖。

使用特权

评论回复
捉虫天师| | 2019-3-25 22:22 | 显示全部楼层
看完不会啊。

使用特权

评论回复
hanzhen654|  楼主 | 2019-3-25 22:27 | 显示全部楼层
frfgfvfd 发表于 2019-3-25 17:09
学习下!很不错的分享帖。

不客气哈,一起学习

使用特权

评论回复
hanzhen654|  楼主 | 2019-3-25 22:27 | 显示全部楼层

总结性的东西,也是很难理解的

使用特权

评论回复
hanzhen654|  楼主 | 2019-3-25 22:27 | 显示全部楼层

多注重实践,多写代码哈

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

73

主题

1766

帖子

2

粉丝