系统相关
首页 > 系统相关> > Linux 进程间通信例程

Linux 进程间通信例程

作者:互联网

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