Linux进程间通信

嵌入式Linux多任务:进程,线程
单任务:一个任务执行完毕之后,下个任务才能执行
多任务:任务的执行可以被中断,中断之后可以执行其他任务(并发,并行)
单核CPU:并发
多核CPU:并发,并行
进程实现多任务:特点:给每个进程分配独立的地址空间,4G大小(1G内核,3G用户空间)
进程创建方式:fork>exec函数族>system>vfork
进程的退出:exit()库函数/清理缓冲
-exit()系统调用/不清理缓冲
进程的等待:wait();解决僵尸进程

学习目标:学会创建多任务进程

进程间通信(IPC)方式

广义上进程间的通信
进程——文件——进程
进程——数据库——进程
例如下面代码所示(通过文件进行通信)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
    pid_t pid;
``  pid = fork();

    if (pid == -1)
    {
        perror("fork error!");
        exit(1);
    }

    if (pid == 0)
    {
        //普通文件
        int fd = open("b.txt", O_CREAT | O_WRONLY, 0655);
        if (fd == -1)
        {
            perror("open file error!");
            exit(1);
        }

        char buf[100] = "hello world";

        write(fd, buf, strlen(buf));

        close(fd);`
    }
    else if (pid > 0)
    {
        sleep(1);
        int fd = open("b.txt", O_RDONLY);
        if (fd == -1)
        {
            perror("open file error!");
            exit(1);
        }

        char buf[100] = {0};

        read(fd, buf, sizeof(buf));

        printf("rec buf = %s\n",buf);

        close(fd);
        return 0;
}

狭义上进程间的通信
分为:管道,信号,消息队列,共享内存,信号量,套接字

管道

无名管道:只允许父子进程间通信
API: int pipe(int pipefd[2]);

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

int main()
{
    pid_t pid;
    int fd[2];
    if (pipe(fd) < 0)
    {
        perror("pipe fork error!");
        exit(1);
    }
    pid = fork();
    if (pid == -1)
    {
        perror("fork error!");
        exit(1);
    }
    if (pid == 0)
    {
    //无名管道
        close(fd[0]);
        char buf[100];
        while (1)
        {
            scanf("%s", buf);
            write(fd[1], buf, strlen(buf));
        }
     }
    else if (pid > 0)
    { 
    char buf[100] = {0};
        while (1)
        {
            int len = read(fd[0], buf, sizeof(buf));
            buf[len] = '\0';
            printf("recv = %s\n", buf);
        }
     return 0;
}

有名管道**:任意两个进程间通信
API: int mkfifo(const char *pathname,mode_t mode)

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

int main()
{
    pid_t pid;
    if (mkfifo("/tmp/p1", 0644) < 0)
    {
        perror("mkfifo error!");
        exit(1);
    }
     pid = fork();

    if (pid == -1)
    {
        perror("fork error!");
        exit(1);
    }

    if (pid == 0)
    {
    int fd = open("/tmp/p1", O_WRONLY);
        if (fd == -1)
        {
            perror("open file error!");
            exit(1);
        }

        char buf[100] = {0};

        while (1)
        {
            scanf("%s", buf);
            write(fd, buf, strlen(buf));
        }
    }
    else if (pid > 0)
    {
    int fd = open("/tmp/p1", O_RDONLY);
        if (fd == -1)
        {
            perror("open file error!");
            exit(1);
        }

        char buf[100] = {0};
        while (1)
        {
            int len = read(fd, buf, sizeof(buf));
            buf[len] = '\0';
            printf("recv = %s\n", buf);
        }
    }

    return 0;
}

下面是任意两个进程间通信的代码
write.c

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

int main()
{
    int fd = open("/tmp/p1", O_WRONLY);
    if (fd == -1)
    {
        perror("open file error!");
        exit(1);
    }

    char buf[100] = {0};

    while (1)
    {
        scanf("%s", buf);
        write(fd, buf, strlen(buf));
    }

    return 0;
}

read.c

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

int main()
{
    if (mkfifo("/tmp/p1", 0644) < 0)
    {
        perror("mkfifo error!");
        exit(1);
    }

    int fd = open("/tmp/p1", O_RDONLY);
    if (fd == -1)
    {
        perror("open file error!");
        exit(1);
    }

    char buf[100] = {0};
    while (1)
    {
        int len = read(fd, buf, sizeof(buf));
        buf[len] = '\0';
        printf("recv = %s\n", buf);
    }

    return 0;
}

消息队列

传送有格式的消息流
多进程网状交叉通信时,消息队列是上上之选
能实现大规模数据通信
API(4个)
int msgget (key_t key,int msgflag) (创建消息队列)
int msgsnd (int msqid,const voidmsgp,size_t msgsz,int msgflg) //将消息写入到消息队列
ssize_t msgrcv (int msqid,void
msgp,size_t msgsz,long msgtyp,int msgflg)//从消息队列读取消息
int msgctl(int msqid,int cmd,struct msqid_ds*buf) //释放消息队列

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

struct msgbuf
{
    /* data */
    long id;
    char buf[100];
};

int main()
{
    pid_t pid;

    key_t key;
    key = ftok("/tmp/1", 'a');

    //msgid消息队列描述符 == 文件描述符
    int msgid = msgget(key, IPC_CREAT | 0644);
    //int msgid = msgget(IPC_PRIVATE, IPC_CREAT | 0644);

    if (msgid < 0)
    {
        perror("msg get error!");
        exit(1);
    }

    pid = fork();

    if (pid < 0)
    {
        perror("fork error!");
        exit(1);
    }

    if (pid == 0)
    {
        //msgid
        struct msgbuf msg;
        msg.id = 1;
        strcpy(msg.buf, "hello world");
        msgsnd(msgid, &msg, sizeof(struct msgbuf), 0);

        msg.id = 2;
        strcpy(msg.buf, "hello world2");
        msgsnd(msgid, &msg, sizeof(struct msgbuf), 0);
        
        msg.id = 3;
        strcpy(msg.buf, "hello world3");
        msgsnd(msgid, &msg, sizeof(struct msgbuf), 0);
    }
    else if (pid > 0)
    {
        //msgid

        struct msgbuf msg;

        msgrcv(msgid, &msg, sizeof(struct msgbuf), 2, 0);

        printf("recv:%s\n", msg.buf);

        wait(NULL);

        msgctl(msgid,IPC_RMID,NULL);
    }

    return 0;
}

共享内存

特点:减少了进入内核空间的次数,效率高

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

int main()
{
    pid_t pid;

    key_t key;
    key = ftok("/tmp/kk", 'k');

    int shmid = shmget(key, 1024, IPC_CREAT | 0644);

    if (shmid < 0)
    {
        perror("shm get error!");
        exit(1);
    }

    pid = fork();

    if (pid < 0)
    {
        perror("fork error!");
        exit(1);
    }

    if (pid == 0)
    {
        //shmid
        void *addr = shmat(shmid, NULL, 0);
        char buf[100] = {0};
        while (1)
        {
            scanf("%s", buf);
            strcpy((char *)addr, buf);
            sleep(1);
        }
    }
    else if (pid > 0)
    {
        //shmid
        sleep(1);

        void *addr = shmat(shmid, NULL, 0);
        while (1)
        {
            if (strlen((char *)addr) > 0)
            {
                printf("recv = %s\n", (char *)addr);
            }
            else
            {
                printf("no data!");
            }
            sleep(1);
            
        }
    }

    return 0;
}

信号量

当多个进程/线程进行共享操作时,用于资源保护,以防止出现相互干扰的情况出现
互斥

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

int main()
{

    pid_t pid;

    key_t key = ftok("/tmp/5", 'p');

    int semid = semget(key, 1, IPC_CREAT | 0644);

    if(semid < 0)
    {
        perror("sem get error!");
        exit(1);
    }
    
    if(semctl(semid,0,SETVAL,1) < 0)
    {
        perror("semctl error!");
        exit(1);
    }

    if ((pid = fork()) < 0)
    {
        perror("frok error!");
        exit(1);
    }

    //b.txt

    if (pid == 0)
    {
        //"hello world\n"

        int fd = open("b.txt", O_WRONLY);
        if (fd == -1)
        {
            perror("open file error!");
            exit(1);
        }
        
        struct sembuf sem;
        sem.sem_num = 0;
        sem.sem_flg = SEM_UNDO;

        while (1)
        {
            //-1  p
            sem.sem_op = -1;
            semop(semid,&sem,1);
            write(fd, "hello", 5);
            write(fd, "world", 5);
            write(fd, "\n", 1);
            sem.sem_op = +1;
            semop(semid,&sem,1);
            //v
            //+1
            //sleep(1);
        }
    }
    else if (pid > 0)
    {
        //"hhhhh wwwww\n"

        int fd = open("b.txt", O_WRONLY);
        if (fd == -1)
        {
            perror("open file error!");
            exit(1);
        }

        struct sembuf sem;
        sem.sem_num = 0;
        sem.sem_flg = SEM_UNDO;

        while (1)
        {
            //-1
            sem.sem_op = -1;
            semop(semid,&sem,1);
            write(fd, "hhhhh", 5);
            write(fd, "wwwww", 5);
            write(fd, "\n", 1);
            sem.sem_op = +1;
            semop(semid,&sem,1);
            //+1
            //sleep(1);
        }
    }

    return 0;
}

未完待续

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值