【linux 文件】管道通信,信号通信

LINUX使用的进程间通信放式:

1)无名管道(pipe)和有名管道(FIFO
2)信号(signal

3)消息队列

4)共享内存

5)信号量

6)套接字(socket

 

一、管道通信

1、管道是单向的,先进先出的,它把一个进程的输出和另一个进程的输入连接在一起

2、一个进程(写进程)在管道的尾部写入数据,另一个进程(读数据)从管道的头部读出数据

 

 

 

无名管道:用于父子进程间的通信

有名管道:用于运行于同一系统中的任一两个进程间的通信

 

1.1无名通道的步骤:创建——读管道——写管道——关闭管道

 

Pipe函数

原型:int pipe(int filedes[2]);

参数:新建的两个描述符有filedes数组返回,filedes[0]表示管家的读取端,filedes[i]表示管道的写入端。

返回值:成功 0,失败-1

头文件:#include<unistd.h>

 

创建管道时要先创建子进程,子进程会继承父进程所有的管道

 

#include<stdio.h>

#include<sys/types.h>

#include<sys/stat.h>

#include<fcntl.h>

#include<unistd.h>

#include<stdlib.h>

 

int main()

{

    int pipe_fd[2];

    pid_t pid;

    int r_num;

    char buf_r[100];

    char *p_wbuf;

    

    memset(buf_r,0,sizeof(buf_r));

    

    if(pipe(pipe_fd)<0)  //创建子程序

    {

        printf("pipe creat error\n");

return -1;

    }

 

    if((pid = fork())==0)//进入子进程

    {

        printf("\n");

// 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);

 

}

if(write(pipe_fd[1],"HELLO WORLD",12)!= -1)

{

    printf("son write3 pipe!\n");

}

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");

    }

    sleep(3)

    close(pipe_fd[1

    sleep(3);

    waitpid(pid,NULL,0);

    exit(0);

}

    }

    return 0;

}

管道是单向的性质决定了在父子进程两端不可以做双向通信。

进程试图读空进程,进程将阻塞;管道已满时,进程在试图向管道内写入数据的时候,也会阻塞

 

1.2有名管道

任意两个进程之间:

创建——删除——打开——关闭——读——写

 

2、mififo函数

作用:创建有名管道

原型:int mkfifo (const char *filename,made_t mode)

参数:filename :有名管道路径,名称

      Mode 管道方式

      1O_NONBLOCK FIFO打开时会立刻返回,非阻塞

      2O_RDONLY  只读

      3O_WRONLY  只写

      4O_RDWR    可读写

 

返回值:成功 0;失败为-1,错误的原因存于errno

 

读程序:

#include<fcntl.h>

#include<stdio.h>

#include<sys/types.h>

#include<sys/stat.h>

#include<stdlib.h>

#include<errno.h>

 

#define FIFO "/tmp/myfifo"

 

int main(int argc,char ** argv)

{

    char buf_r[100];

    int fd;

    int nread;

 

   /*创建管道*/

 if((mkfifo(FIFO,O_CREAT|O_EXCL)<0)&&(errno != EEXIST))

    {

        printf("cannot creat fifoserver\n");

    }

    printf("Preparing 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 day yet\n");

    }

}

printf("read %s from FIFO\n",buf_r);

sleep(1);

    }

    pause();

    unlink(FIFO);

}

 

写程序:

#include<stdio.h>

#include<sys/types.h>

#include<sys/stat.h>

#include<fcntl.h>

#include<errno.h>

#include<string.h>

 

#define FIFO_SERVER "/tmp/myfifo"

 

int main(int argc,char**argv)

{

    int fd;

    char w_buf[100];

    int nwrite;

    int pipe_fd[2];

    pid_t pid;

    /*打开管道*/

    fd = open(FIFO_SERVER,O_WRONLY|O_NONBLOCK,0);

 

    if(argc == 1)

    {

        printf("Please send somethong\n");

exit(-1);

    }

    if(pipe(pipe_fd)<0)

    {

     printf("pipe error!\n");

    }

    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 again\n");

}

else

{

    printf("write %s to the fifo\n",w_buf);

}

    }

}

注意:以上两个程序在执行的时候,要同时打开两个终端,先打开读程序执行创建管道,在打开写程序执行。否则,管道阻塞,写的内容不会保存在管道中。

 

二、信号通信

常见信号

 SIGHUP: 从终端上发出的结束信号

 SIGINT: 来自键盘的中断信号(Ctrl-C

 SIGKILL:该信号结束接收信号的进程,杀死进程

 SIGTERMkill 命令发出的信号

 SIGCHLD:子进程停止或结束时通知父进程

 SIGSTOP:来自键盘(Ctrl-Z)或调试程序的停止执行信号,暂停进程

 

当某信号出现时,将按照下列三种方式中的一种进行处理:

1、忽略此信号

     大多数信号都按照这种方式进行处理,但有两种信号

决不能被忽略,它们是:

SIGKILL\SIGSTOP

这两种信号不能被忽略的原因是:它们向超级用户提供了一种终止或停止进程的方法

 

2、执行用户希望的动作

通知内核在某种信号发生时,调用一个用户函数。在用户函数中,执行用户希望的处理

 

3、执行系统默认动作

对大多数信号的系统默认动作是终止该进程

 

2.1  kill函数

作用:传送信号给指定的进程

原型:int kill pid_t pid,int sig

参数:pid : >0 指定的进程PID

          =0 发送给目前进程相同进程组的所有进程

          =-1 广播给系统内所有的进程

          < 0 将信号发送给其进程组ID等于pid绝对值的进程。

 

2.2 raise函数

功能:发送信号给自身

原型:int raise int sig

头文件:#include <signal.h>

 

2.3 alarm函数

作用:设置信号传送给信号

原型: unsigned int alarm (unsigned int seconds)

返回值:返回之前闹钟的剩余秒数,若没有设置闹钟,返回0

头文件:#include <signal.h>

 

2.4 pause函数

作用:让进程暂停,直到信号被中断

原型:int pause(void)

返回值:-1

 

2.5 signal

作用:设置信号方式

原型:void (*signal int signumvoid*handler)(int)))(int);

 

 

例程:

#include<stdio.h>

#include<signal.h>

 

void my_func(int sign_no)

{

    if(sign_no == SIGINT)

    {

        printf("I have a signal SIGINT\n");

    }

    if(sign_no == SIGQUIT)

    {

        printf("I have a signal SIGOUT\n");

    }

}

 

int main()

{

    printf("waiting for signal SIGINT or SIGOUT\n");

 

    signal(SIGINT,my_func);

    signal(SIGQUIT,my_func);

    pause();

    exit(0);

}

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值