ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

Linux 进程间通信例程

2021-12-26 18:58:12  阅读:159  来源: 互联网

标签:perror addr 例程 间通信 int fd Linux include struct


1、pipe
 1)只能用于具有亲缘关系的进程间通信
 2)半双工通信,具有相同的读写端

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    int pfd[2];
    int pid;
    int data = 23;
    
    //create pipe
    if(pipe(pfd) < 0)
    {
        //failed 
        perror(" create pipe failed !\n");
        return -1;
    }
    else
    {
        if((pid = fork()) < 0)
        {
            perror("create process failed !\n");
        }
        else if(pid > 0)
        {
            //parent process 
            close(pfd[0]);
            write(pfd[1],&data, sizeof(int));
            close(pfd[1]);
        }
        else
        {
            //child process
            close(pfd[1]);
            read(pfd[0],&data,10);
            close(pfd[0]);
        }
    }
        
}

内核实现步骤总结:
1. 初始化管道文件系统
2. 注册和加载文件系统
3. 建立write,read管道,返回文件以及文件描述符
4. 写和读
5. close
======================
do_pipe_flag
    create_write_pipe
        get_pipe_info
            alloc_pipe_info
    create_read_pipe
    get_unused)fd_flags
    fd_install 
======================

2、fifo
mkfifo(const char *pathname,mode_t mode); 

read例程:

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

#define FIFO_PATH "my_fifo_file"

//read fifo
int main(void)
{
    int fd;
    char cont[255];
    //create fifo file
    if(mkfifo(FIFO_PATH,0666) < 0  && error != EEXIST)
    {
        perror("create fifo failed !\n");
        return -1;
    }
    else
    {
        printf("create fifo success !\n");
        //open file 
        fd = open(FIFO_PATH,O_CREATE|O_RDONLY,0666);
        if(fd >0)
        {
            //read cont
            while(1)
            {
                read(fd,cont,255);
                printf("read : %s !\n",cont);
            }
            close(fd);
        }
        else
        {
            perror("open failed !\n");
        }
        
        return 0;
    }
    
}

write例程:

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

#define FIFO_PATH "my_fifo_file"

//read fifo
int main(void)
{
    int fd;
    char cont[] = " hello test";
    //create fifo file
    if(mkfifo(FIFO_PATH,0666) < 0 && error != EEXIST)
    {
        perror("create fifo failed !\n");
        return -1;
    }
    else
    {
        printf("create fifo success !\n");
        //open file 
        fd = open(FIFO_PATH,O_CREATE|O_RDONLY,0666);
        if(fd >0)
        {
            //read cont
            while(1)
            {
                write(fd,cont,strlen(cont));
                printf("write success !\n");
            }
            close(fd);
        }
        else
        {
            perror("open failed !\n");
        }
        
        return 0;
    }
    
}

3、 siginal
1. 软中断信号:用来通知进程发生了异步事件。进程之间可以互相通过系统调用kill发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。
2. 信号只是用来通知进程发生了什么事件,并不给该进程传递任何数据。

//发送信号
1)想进程本身发送信号
    int raise(int SIGNO);
2)向指定进程发送信号
    int kill(pid_t pid,int SIGNO)
3) 特殊发送信号函数,比如:
    unsigned int alarm(unsigned int seconds);
4) 等待信号
    pause()

5) 内核代码跟踪
    do_tkill
        do_sned_soecific
            do_send_sig_info
                send_signal 
                    __send_signal

typedef void (*sighandler_t)(int);
sighandler_t signal(int signum,sighandler_t handler);

/********************************/
#include <stdio.h>
#include <signal.h>
#include <unistd.h>

void sig_handler(int sig_no)
{
    if(sig_no == SIGINT)
    {
        printf(" get sigint !\n");
    }
    else if(sig_no == SIGQUIT)
    {
        printf("get SIGQUIT !\n");
    }
}


int main()
{
    printf("waiting for signal !\n");

    //register signal 
    signal(SIGINT,sig_handler);
    signal(SIGQUIT,sig_handler);
    pause();
}

4、共享内存

write例程:

#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <string.h>
#include <stdio.h>

int main(void)
{
    void *shm_addr;
    int shmid;
    char cont[] = "hello test";
    
    //1. create share memory 
    shmid = shmget(12345,2048,IPC_CREATE|0666);
    if(shmid != -1)
    {
        //2. map address 
        shm_addr = shmat(shmid,NULL,0);
        if(share_memory != (void *)-1)
        {
            //copy mem 
            memcpy(shm_addr,cont,sizeof(cont));
            printf("save success !\n");
            
            shmdt(shm_addr);
        }
        else
        {
            perror("shmat:");
        }
    }
    else
    {
        perror("shmget");
    }
    
    
    return 0;
}

read例程:

#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <string.h>
#include <stdio.h>

int main(void)
{
    void *shm_addr;
    int shmid;
    char cont[] = "hello test";
    
    //1. create share memory 
    shmid = shmget(12345,2048,IPC_CREATE|0666);
    if(shmid != -1)
    {
        //2. map address 
        shm_addr = shmat(shmid,NULL,0);
        if(share_memory != (void *)-1)
        {
            printf("get data  = %s !\n",(char *)shm_addr);
            
            shmdt(shm_addr);
        }
        else
        {
            perror("shmat:");
        }
    }
    else
    {
        perror("shmget");
    }
    
    
    return 0;
}

5 消息队列
1、数据读一遍数据之后,数据就不存在了(消息被取走之后就不存在了)
2、默认的配置会导致阻塞,可以在recv 和snd 函数中设置NOWAIT

send例程:

#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <string.h>
#include <stdio.h>

struct magbuf
{
    long mtype;
    char ntext[255];
};

int main()
{
    struct msgbuf mybuf;
    int msggid = 0;
    mybuf.mtype = 1;
    strcpy(mybuf.ntext,"hello test");
    
    //1. create message queue
    msggid = msgget(2345,IPC_CREATE|0666);
    if(msggid == -1)
    {
        //2. send message queue 
        if(msgsnd(msggid,&mybuf,sizeof(mybuf.ntext),0)!= -1)
        {
            printf("sned message success !\n");
        }
        else
        {
            perror(" send error !\n");
        }
    }
    else
    {
        perror("msgget error !\n");
    }

    return 0;
}

recv例程:

#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <string.h>
#include <stdio.h>

struct magbuf
{
    long mtype;
    char ntext[255];
};

int main()
{
    struct msgbuf mybuf;
    int msggid = 0;
    
    //1. create message queue
    msggid = msgget(2345,IPC_CREATE|0666);
    if(msggid == -1)
    {
        //2. send message queue 
        if(msgrecv(msggid,&mybuf,sizeof(mybuf.ntext),1,0)!= -1)
        {
            printf("recv message success ; %s !\n",mybuf.ntext);
            
            //3. delete queue 
            if(msgctl(msggid,IPC_RMID,0) != -1)
            {
                printf(" delete queeu success !\n");
            }
        }
        else
        {
            perror(" recv error !\n");
        }
    }
    else
    {
        perror("msgget error !\n");
    }
    
    return 0;
}

6、信号量 semphore

操作流程:
1. 建立信号量
2. 操作信号量
3. lock unlock

#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h>
#include <string.h>
#include <stdio.h>

int semid = 0;

struct sembuf sem_down = {0,-1,0};
struct sembuf sem_up = (0,1,0);


void down()
{
    semop(semid,&sem_down,1);
}

void up()
{
    semop(semid,&sem_up,1);
}

int main()
{
    
    //1. create sem 
    semid = semget(2345.1,IPC_CREATE|0666);
    if(semid != -1)
    {
        //2. set semaphore = 1
        semctl(semid,1,SETVAL);
        
        //3. locl unlock 
        down(); // lock 
        printf(" hello test !\n");
        
        up(); // unlock 
    }
    else
    {
        perror("semget error !\n");
    }
    
    return 0;
}

7、

7) socket 

//socket 常用函数
socket -- create an endpoint for communication 
    int socket(int domain,int type,int protocol);
bind -- bind a name to a socket 
    int bind(int sockfd,const struct sockaddr *addr, socklen_t addrlen);
listen -- listen for connections on a socket 
    int listen(int sockfd,int backlog);
accept -- accept a connections on a socket 
    int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);

read ,write ,close 

send,sendto ,sendmsg -- send a message to a socket 
    ssize_t send(int sockfd,const coid *buf,size_t len,int flags);
    ssize_t snedto(int sockfd,const void *buf,size_t len,int flags,const struct sockaddr *dest_addr,socklen_t addrlen);
    ssize_t sendmsg(int sockfd,const struct msghdr *msg,int flags);

recv,recvfrom,recvmsg -- receive a message from a socket 

server例程:

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


//server.c 
int main()
{
    int server_fd;
    int client_fd;
    struct sockaddr_un myaddr;
    struct sockaddr_un client_addr;
    myaddr.sun_family = AF_UNIX;
    strcpy(myaddr.sun_path,"testsockfile");
    int client_addr_len = sizeof(client_addr);
    
    
    //1.socket 
    server_fd = socket(AF_UNIX,SOCK_STREAM,0);
    if(serverfd == -1)
    {
        printf("socket error !\n");
        exit(1);
    }
    // 2.bind
    if(bind(serverfd,(struct sockaddr *)&myaddr,sizeof(myaddr)) == -1)
    {
        perror("bind error !\n");
        exit(1);
    }
    // 3. listen
    if(listen(server_fd,20 ) == -1) // 20 times 
    {
        perror("listen error !\n");
        exit(1);
    }
    // 4. accept
    client_fd = accept(server_fd,(struct sockaddr *)&client_addr,&client_addr_len);
    if(client_fd == -1)
    {
        perror("accept error !\n");
        exit(1);
    }
    // 5. op 
    write(client_fd,"hello test",10);

    // 6. close    
    close(client_fd);
    close(server_fd);
    
    return 0;
}

client例程:

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


//client.c 
int main()
{
    int server_fd;
    int client_fd;
    char buf[100];
    struct sockaddr_un myaddr;
    struct sockaddr_un client_addr;
    myaddr.sun_family = AF_UNIX;
    strcpy(myaddr.sun_path,"testsockfile");
    int client_addr_len = sizeof(client_addr);
    
    
    //1.socket 
    server_fd = socket(AF_UNIX,SOCK_STREAM,0);
    if(serverfd == -1)
    {
        printf("socket error !\n");
        exit(1);
    }

    //2.connect 
    if(connect(serverfd,(struct sockaddr *)&myaddr,sizeof(myaddr)) == -1)
    {
        perror("connect error !\n");
        exit(1);
    }
   
    // 3. op 
    read(serverfd,buf,100);
    printf(" get server data = %s !\n",buf);
    // 6. close    
    close(server_fd);
    
    return 0;
}

标签:perror,addr,例程,间通信,int,fd,Linux,include,struct
来源: https://blog.csdn.net/jansert/article/details/122158803

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有