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

来源:互联网 发布:今日非农数据结果 编辑:程序博客网 时间:2024/06/04 18:41

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 (*signalint 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
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 孩子上幼儿园哭老师不理孩子怎么办 发现幼儿园给孩子吃药片该怎么办 做老师的打学生被家长投诉怎么办 学生认为老师向家长打报告怎么办 老师发打12分的试卷给家长怎么办 孩子在学校顶撞老师不让上学怎么办 被老师骂了不敢去学校怎么办 孩子不爱去幼儿园 总是哭怎么办呢 孩子在幼儿园被老师罚家长该怎么办 孩子不喜欢幼儿园里的体能课怎么办 初中叛逆期的孩子怎么办老师做法 二年级孩子不受老师待见怎么办 孩子该上初中了没学籍怎么办 四个多月的婴儿不喜欢看人怎么办 2个月婴儿不喜欢吃奶粉怎么办 想学习但是又学不进去怎么办 在省外读书 回来读高中学籍怎么办 一岁宝宝这几天不爱吃饭怎么办 2岁的宝宝吃多了怎么办 小孩吃了退烧药吐了怎么办 牙齿与牙齿之间有洞喜欢塞牙怎么办 胃有点烧心天天没食欲不饿怎么办 1岁半宝宝不吃饭光喝奶粉怎么办 一岁半宝宝光喝奶粉不吃饭怎么办 一岁半的宝宝光喝奶粉不吃饭怎么办 两岁半宝宝光喝奶粉不吃饭怎么办 宝宝9个月不好好吃饭奶粉怎么办 2岁半宝宝不愿意自己吃饭怎么办 一周岁多的宝宝不吃饭怎么办 一岁宝宝吃母乳不爱吃饭怎么办 三个月大的宝宝不肯喝奶粉怎么办 自己要上班婆婆带孩子看不惯怎么办 让农村婆婆来给我带孩子怎么办 吃的不好胃难受怎么办吃什么药 特别讨厌婆婆还需要她带小孩怎么办 一岁八个月宝宝不喜欢穿袜子怎么办 未来婆婆给我买衣服我不喜欢怎么办 孩子调皮被同学排斥不想上学怎么办 宝宝出生没人带怎么办自己要上班 孩子上幼儿园一年了还哭怎么办 6年级孩子会认字不会写怎么办