进程间通信---无名管道、有名管道、信号通信、共享内存、消息队列、信号灯、socket

进程间通信---无名管道、有名管道、信号通信、共享内存、消息队列、信号灯、socket

数据库:动态库.os 静态库.a  /lib  /usr/lib

        不同1. .a  .so

               2.使用时刻不同      静态编译     动态运行

               3.可移植性    静态可移植

通信领域的几个概念:

        单工通信:数据的传送方向为单向

        半双工通信:数据的传送方向为双向,但不同时

        全双工通信:数据的传送方向为双向且同时

1.无名管道

        无名管道是用pipe创建的一个内核文件,用于具有亲缘关系的进程间的通信。

                int pipe(int pipefd[2]);

                        pipefd[2]:数组,fd[0]用来标识读管道文件

                                                fd[1]用来标识写管道文件

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

#include
#include
#include

#define BUF_SIZE 20

int main()
{
    //1.pipe
    int fd[2] = {0};
    if(0 != pipe(fd))
    {
        printf("create pipr error!!\r\n");
        return -1;
    }
    printf("1:create pipe ok!\r\n");
    //2.fork
    pid_t pid = -1;
    pid = fork();
    if(-1 == pid)
    {
        return -1;
    }
    char buf[BUF_SIZE] = {0};
    if(0 == pid)
    {
        //child write
        close(fd[0]);
        printf("child process!\r\n");
        strcpy(buf,"child to parent");
        write(fd[1],buf,BUF_SIZE);
    }
    else
    {
        //parent read
        close(fd[1]);
        printf("parent process!\r\n");
        read(fd[0],buf,BUF_SIZE);
        printf("parent read:%s\r\n",buf);
    }
}

特点:

        1.只能用于具有亲缘关系的进程间通信

        2.是一种单工通信模式(理论上是双工的,但是通信双方的收发顺序不好控制,通常用作单工)

        3.无名管道的数据存放在内存中,管道中的数据读走后就不存在了,无名管道只存在于内核中,在文件系统中不可见

2.有名管道

        有名管道是用mkfifo创建的一个内核文件,用于任意两个进程之间的通信,管道文件在文件系统中可见。

        int mkfifo(const char *pathname, mode_t mode);

        作用:创建一个有名管道文件

        *pathname:有名管道文件的名称

        mode:文件权限

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

        ret = mkfifo("fifo",0666);

        if(ret<0&&EEXIST!=errno)-->创建文件失败并且该文件不存在

        {

                return -1;//创建文件失败

        }

        创建文件失败但是该文件存在==>创建文件成功

      A:

        1.mkfifo ---> 有名称

        2.open

        3.write

      B:

        1.mkfifo

        2.open

        3.read

单工

#include
//#include
#include
#include
#include
#include
#include

#define BUF_SIZE 20

int mian()
{
    //1.mkfifo
    int ret = -1;
    ret = mkfifo("fifo",0666);
    if(ret < 0&& EEXIST != errno)
    {
        return -1;
    }
    printf("create fifo ok!---\r\n");
    //2.open
    int fd = open("fifo",O_WRONLY,0666);
    if(-1 == fd)
    {
        return -1;
    }
    printf("2:open fifo ok!--------\r\n");
    //3.write
    char buf[BUF_SIZE] = {0};
    strcpy(buf,"hello 22101");
    write(fd,buf,BUF_SIZE);
    //4.close
    close(fd);
    return 0;
}//A
#include
//#include
#include
#include
#include
#include
#include

#define BUF_SIZE 20

int mian()
{
    //1.mkfifo可要可不要
    int ret = -1;
    ret = mkfifo("fifo",0666);
    if(ret < 0&& EEXIST != errno)
    {
        return -1;
    }
    printf("create fifo ok!---\r\n");
    //2.open
    int fd = open("fifo",O_RDONLY,0666);
    if(-1 == fd)
    {
        return -1;
    }
    printf("2:open fifo ok!--------\r\n");
    //3.read
    char buf[BUF_SIZE] = {0};
    read(fd,buf,BUF_SIZE);
    printf("read ok!buf = %s\r\n",buf);
    //4.close
    close(fd);
    return 0;
}//B

 双工

#include
//#include
#include
#include
#include
#include
#include

#define BUF_SIZE 20

int mian()
{
    //1.mkfifoa
    int ret = -1;
    ret = mkfifo("fifoa",0666);
    if(ret < 0 && EEXIST != errno)
    {
        return -1;
    }
    printf("create fifoa ok!---\r\n");
    //mkfifob
    ret = mkfifo("fifob",0666);
    if(ret < 0 && EEXIST != errno)
    {
        return -1;
    }
    printf("create fifob ok!---\r\n");
    //3.open fifoa
    int fdw = open("fifoa",O_WRONLY,0666);
    if(-1 == fdw)
    {
        return -1;
    }
    printf("3:open fifoa ok!--------\r\n");
    //4.open fifob
    int fdr = open("fifob",O_RDONLY,0666);
    if(-1 == fdr)
    {
        return -1;
    }
    printf("4:open fifob ok!--------\r\n");

    char buf[BUF_SIZE] = {0};
    while(1)
    {
        //5.write
        memset(buf,0,BUF_SIZE);
        fgets(buf,BUF_SIZE,stdin);//get(buf);
        write(fdw,buf,BUF_SIZE);
        
        //6.read
        memset(buf,0,BUF_SIZE);
        read(fdr,buf,BUF_SIZE);
        printf("b->a: %s\r\n",buf);
    }
    //7.close
    close(fdw);
    close(fdr);
    return 0;
}//A
#include
//#include
#include
#include
#include
#include
#include

#define BUF_SIZE 20

int mian()
{
    //1.mkfifoa可要可不要
    int ret = -1;
    ret = mkfifo("fifoa",0666);
    if(ret < 0 && EEXIST != errno)
    {
        return -1;
    }
    printf("create fifoa ok!---\r\n");
    //2.mkfifob可要可不要
    ret = mkfifo("fifob",0666);
    if(ret < 0 && EEXIST != errno)
    {
        return -1;
    }
    printf("create fifob ok!---\r\n");
    //3.open fifoa
    int fdr = open("fifoa",O_WRONLY,0666);
    if(-1 == fdr)
    {
        return -1;
    }
    printf("3:open fifoa ok!--------\r\n");
    //4.open fifob
    int fdw = open("fifob",O_RDONLY,0666);
    if(-1 == fdw)
    {
        return -1;
    }
    printf("4:open fifob ok!--------\r\n");

    char buf[BUF_SIZE] = {0};
    while(1)
    {
        
        //5.read
        memset(buf,0,BUF_SIZE);
        read(fdr,buf,BUF_SIZE);
        printf("a->b: %s\r\n",buf);

        //6.write
        memset(buf,0,BUF_SIZE);
        fgets(buf,BUF_SIZE,stdin);//get(buf);
        write(fdw,buf,BUF_SIZE);
    }
    //7.close
    close(fdw);
    close(fdr);
    return 0;
}//B

进程间通信---无名管道、有名管道、信号通信、共享内存、消息队列、信号灯、socket_第1张图片

 特点:

        1.有名管道可以用于任意两个进程间的通信

        2.有名管道可以实现双工通信(需要两个管道文件)

        3.有名管道中的数据存放在内存中,管道中的数据读走后就不存在了,有名管道文件在文件系统中可见,文件大小为0

3.信号通信

异步通信:被通信方不知道什么时候跟它通信

同步通信:发送方发数据,接收方收数据,双方需要在很短的时间内完成数据交换,否则会造成一方阻塞。

信号:信号是对中断的模拟,信号通信是一种异步通信方式,是一个通知

中断:是指CPU在执行程序的工程中插入了另外一段程序的过程

信号:Linux操作系统预先定义好了64个信号

        kill -l 查看当前系统提供的所有信号

        kill -9 进程号:给内核发送SIGKILL信号,让内核杀死指定进程

用户进程对信号的响应方式:捕获信号、忽略信号、采用默认处理动作

#include
#include

int main()
{
    alarm(2);
    printf("hello\r\n");
    pause();//挂起
    printf("world\r\n");
    return 0;
}
#include
#include
#include

void Func(int signo)
{
    printf("into Func:signo = %d\r\n",signo);
}
int main()
{
    signal(SIGALRM,Func);
    alarm(2);
    printf("hello\r\n");
    while(1)
    {
        pause();
    }
    printf("world\r\n");
    return 0;
}

signal(信号,自定义的信号对应的处理函数)--->用来改变一个信号对应的默认处理动作

分析:alarm singal使用过程    信号处理流程-->alarm——test.c

#include
#include
#include

void Func(int signo)
{
    printf("into Func:signo = %d\r\n",signo);
}
int main()
{
    signal(SIGALRM,Func);
    alarm(2);
    printf("hello\r\n");
    pause();
    printf("world\r\n");
    return 0;
}

实现两个进程的异步通信:

        A:收信号进程 :signal pause

        B:发信号进程:kill()

                int kill(pid_t pid,int sig)

                pid:对方进程号

                sig:发的信号

#include
#include
#include
#include

int main(int argc,char *argv[])
{
    if(2 != argc || NULL == argv[1])
    {
        return -1;
    }
    int pid = atoi(argv[1]);
    if(pid <= 0)
    {
        return -1;
    }
    kill(pid,SIGUSR1);
    return 0;
}//发信号程序
#include
#include
#include

void SigFunc(int signo)
{
    printf("signo =%d\r\n",signo);
    if(SIGUAR1 == signo)
    {
        printf("sig user1---------\r\n");
        printf("hello\r\n");
    }
    else
    {
        printf("sig user2---------\r\n");
        printf("world\r\n");
    }
}
int main()
{
    printf("pid = %d\r\n",getpid());
    signal(SIGUSR1,SigFunc);
    signal(SIGUSR2,SigFunc);
    while(1)
    {
        pause();
    }
}

4.共享内存:

 A:1. ftok(".",int a)--->flag--->B进程通过该flag找到A进程

        2. shmget

        3. shmat

        4. memcpy

  B:1. ftok

        2.shmget

        3.shmat

        4.printf()

        key_t ftok(const char *pathname,int proj_id);

                作用:生成对方进程找到自己的标识符

                *pathname:用户指定的路径,可以是“.”,或“/home/farsight/.”

                proj_id:0~255

                返回值:成功 :产生一个key值;失败:-1

         int shmget(key_t key,int size,int shmflg);

                作用:创建一块共享内存

                key:ftok的返回值或IPC_PRIVATE                

                size:共享内存大小

                shmflg:操作共享内存的权限

                返回值:成功shmID->标识创建成功的共享内存; 失败:-1

        void *shmat(int shmid,const void *shmaddr,int shmflg);

                作用:将本地内存和共享内存建立映射

                shmid:共享内存的标识符,shmget 的返回值

                *shmaddr:指向本地内存地址的指针,一般给NULL

                shmflg:SHM_RDONLY-->共享内存只读

                                0-->共享内存可读写

                返回值:指向映射成功后的本地内存地址

        int shmdt(const void *shmaddr);

                作用:取消映射

                *shmaddr:映射成功后的本地内存地址,shmat的返回值

        int shmctl(int shmid,int cmd,struct shmid_ds *buf);

                作用:设置或获取共享内存属性

                shmid:共享内存的标识符 shmget的返回值

                cmd:操作选项IPC_STAT(获取对象属性)

                                        IPC_SET(设置对象属性)

                                        IPC_RMID(删除对象)

                *buf:指向共享内存的属性值,IPC_STAT或IPC_SET时使用,IPC_RMID时该设置为NIULL

5.消息队列

  A:1. ftok

        2. msgget

        3. 创建消息结点

        4. msgsnd

  B:1. ftok

        2. msgget

        3.msgrcv 

int msgget(ket_t key, int msgflg);

        作用:创建一个消息队列

        key : ftok的返回值

        msgflg:IPC_CREAT|访问权限

         返回值:成功 :消息队列ID;失败:-1

消息节点:一般有消息类型和消息正文组成

        struct msgbuf

        {

                long m_type;//消息类型

                char buf[BUF_SIZE];//消息正文,BUF_SIZE为消息大小

        }

int masgsnd(int msqid,const void *msgp,size_t msgsz,int msgflg);

        作用:给消息队列发消息

        msqid:消息队列ID

        msgsz:消息的大小

        msgflg:IPC_NOWAIT 消息没有发送完成函数也会立即返回。

                                0:直到发送完成函数才返回

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

ssize_t msgrcv(int msqid,void *msgp,size_t msgsz,long msgtyp,int msgflg);

        作用:从消息列队中读消息

       msqid:消息队列ID

         msgp:指向存放消息的结构体

         msgsz:消息的大小

         msgtyp:0:接收消息队列中的第一个消息

                                        >0:按照消息类型接收消息(若同类型的消息有多个,先进先出原则接收)

 6.信号灯/量

Linux系统提供了三种信号灯:

        1.无名信号灯----> sem_t  sema---->用于线程间同步

        2.有名信号灯---->sem_open ---->用于线程间同步

        3.信号灯集----->多个信号灯的集合---->用于多个进程或线程间的同步

有名信号灯:

        sem_t *sem_open(const char *name,int oflag,mode_t mode,unsigned int value);

                作用:创建有名信号灯

                *name:信号灯的名称

                oflag:动作控制参数O_CREAT O_EXCL

                mode:权限

                value:信号灯的初值

                返回值:指向创建成功的信号灯

#include
#include
#include
#include
#include

int main()
{
    //1.create sem
    sem_t *pSemA = sem_open("aaa",O_CREAT,0666,1);
    if(SEM_FAILED == pSenA)
    {
        return -1;
    }
    printf("1:pSemA  ok!------\r\n");
    sem_t *pSemB = sem_open("bbb",O_CREAT,0666,0);
    if(SEM_FAILED == pSemB)
    {
        return -1;
    }
    printf("2:pSemB ok!-------\r\n");
    while(1)
    {
        sem_wait(pSemA);
        printf("hello\r\n");
        sleep(1);
        sem_post(pSemB);
    }
}
#include
#include
#include
#include
#include

int main()
{
    //1.create sem
    sem_t *pSemA = sem_open("aaa",O_CREAT,0666,1);
    if(SEM_FAILED == pSenA)
    {
        return -1;
    }
    printf("1:pSemA  ok!------\r\n");
    sem_t *pSemB = sem_open("bbb",O_CREAT,0666,0);
    if(SEM_FAILED == pSemB)
    {
        return -1;
    }
    printf("2:pSemB ok!-------\r\n");
    while(1)
    {
        sem_wait(pSemB);
        printf("world\r\n");
        sleep(1);
        sem_post(pSemA);
    }
}

你可能感兴趣的:(网络)