linux进程通信

一、无名管道: pipe            ---父子进程通信
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
(1). fd[2] = {0};   ---无名管道文件描述符,读 管道文件描述符:fd[0], 写 管道文件描述符:fd[1]

(2). pipe(fd);      ---生成无名管道函数,返回0成功,-1失败

(3). pid_t pid = fork();        ---生成子进程函数,返回-1失败,0子进程,大于0父进程

(4). write(fd[1], buf, strlen(buf));            ---向无名管道 写 数据
    wait(NULL);                                 ---等待一个子进程退出
    fcntl(fd[0], F_SETFL, O_NONBLOCK);          ---设置 无名管道 不阻塞
    read(fd[0], buf, sizeof(buf));              ---从无名管道 读 数据
    
    waitpid(pid);                       ---等待pid子进程退出


二、有名管道:mkfifo               ---非父子进程或父子进程通信
(1). if(access("../myMkfifo", F_OK) != 0)           ---判断有无 ../myMkfifo 管道文件, 有返回0, 无返回-1

(2). mkfifo("../myMkfifo", 0666);           ---创建有名管道文件,返回0成功,-1失败

(3). fd = open("../myMkfifo", O_WRONLY);            ---打开管道文件
    write(fd, buf, strlen(buf))                     ---管道文件写数据,其他进程也可以 打开管道文件,读 写 数据
    
    
三、信号:signal             ---通过信号 进程间通信,挂起进程、杀死进程....,SIGINT, SIGQUIT, SIGUSR1, SIGKILL等, kill -l命令查看
#include <signal.h>
(1). signal(SIGINT, signalHandler);             ---改变信号SIGINT的 实现函数, 函数为 signalHandler 参数

    void signalHandler(int signum)
    {
        if(signum == SIGINT){
            printf("rcv SIGINT!\n");
        }
        else{
            printf("rcv other signal!\n");
        }
    }
    
    signal(SIGINT, SIG_DFL);                ---恢复信号默认值
    
(2). kill(pid, SIGINT);                     ---向进程 pid 发送信号SIGINT


四、共享内存: shm             ---
#include <sys/ipc.h>
#include <sys/shm.h>
(1). int projId = rand();
    key_t key = ftok("../", projId);             ---生成共享内存的键值, 返回-1失败
    
(2). int shmId = shmget(key, 1024, IPC_CREAT | 0666);           ---创建共享内存id,大小为1024, 返回-1失败
    system("ipcs -m");                              ---查看共享内存
    
(3). char *shmAddr = shmat(shmId, NULL, SHM_RDONLY);            ---将共享内存映射到进程,返回映射地址shmAddr
    strcpy(shmAddr, "hello cying!\n");                  ---往共享内存写数据
    
(4). shmdt(shmAddr);                ---在进程中卸载共享内存shmAddr

(5). shmctl(shmId, IPC_RMID, NULL);             ---删除共享内存id


五、消息队列: msg             ---
#include <sys/msg.h>
(1). int projId = rand();
    key_t key = ftok("../", projId);             ---生成共享内存的键值, 返回-1
    
(2). int msgId= msgget(key, IPC_CREAT | 0666);              ---创建消息队列id, 返回-1失败
     system("ipcs -q");

(3). struct msgbuf                              ---消息队列通信结构体
    {
        long mtype;                                 ---消息类型
        char mtext[1024-sizeof(long)];              ---文本长度
    };
    struct msgbuf buf;
    buf.mtype = 1;
    strcpy(buf.mtext, "hello cherry!");
    
    msgsnd(msgId, &buf, strlen(buf.mtext), 0);          ---消息队列 数据发送, 最后一个参数msgflg(0, IPC_NOWAIT, MSG_COPY, MSG_EXCEPT, MSG_NOERROR)
    
    int recv_len = msgrcv(msgId, &buf, sizeof(buf.mtext), 1, 0);        ---数据接收,返回接收长度, 倒数第二个参数消息类型:1
    
(4). msgctl(msgId, IPC_RMID, NULL);             ---删除消息队列id

              

六、system V 同步与互斥---信号量: sem                      ---
#include <sys/sem.h>
1>  void P(int semId)
    {
        struct sembuf buf = {0, -1, SEM_UNDO};                  
        int ret = semop(semId, &buf, 1);                
    }

    void V(int semId)
    {
        struct sembuf buf = {0, 1, SEM_UNDO};
        int ret = semop(semId, &buf, 1);                    
    }
    
    struct sembuf
    {
        unsigned short sem_num;  /* semaphore number */
        short          sem_op;   /* semaphore operation */
        short          sem_flg;  /* operation flags */                  ---IPC_NOWAIT和SEM_UNDO
    };

2> system V 互斥(mutex)
(1). int projId = rand() % 255;
    key_t key = ftok("../myFtok", projId);
    
(2). int semId = semget(key, 1, IPC_CREAT | 0666);              ---创建信号集id, 信号量个数为1
    system("ipcs -s");
    
(3). int ret = semctl(semId, 0, SETVAL, 1);                 ---设置arg.val 初值

(4). 父进程:
    P(semId);
    其他要执行的操作...;
    V(semId);
    
    子进程:
    P(semId);
    其他要执行的操作...;
    V(semId);
    
(5). semctl(semId, 0, IPC_RMID);

3> system V 同步(sync)
(1). int projId = rand() % 255;
    key_t key1 = ftok("../myFtok", projId);
    key_t key2 = ftok("../myFtok", projId);
    
(2). int semId1 = semget(key1, 1, IPC_CREAT | 0666);              ---创建信号集id1, 信号量个数为1
    int semId2 = semget(key2, 1, IPC_CREAT | 0666);              ---创建信号集id2, 信号量个数为1
    system("ipcs -s");
    
(3). int ret = semctl(semId1, 0, SETVAL, 1);
    int ret = semctl(semId2, 0, SETVAL, 0);

(4). val1 = semctl(semId_1, 0, GETVAL, 0);              ---获取arg.val 的值
    val2 = semctl(semId_2, 0, GETVAL, 0);
    父进程:
    P(semId1);
    其他要执行的操作...;
    V(semId2);
    
    子进程:
    P(semId2);
    其他要执行的操作...;
    V(semId1);
    
(5). semctl(semId1, 0, IPC_RMID);
    semctl(semId2, 0, IPC_RMID)
    
    
    
七、POSIX 同步与互斥
#include <semaphore.h>
1> 互斥(mutex)
(1). sem_t *semId_1 = sem_open("sem_1", O_CREAT, 0666, 1);            ---创建并打开 名为 sem_1的POSIX信号量,返回semId, arg.val初值是 0

(2). 父进程:
    sem_wait(semId_1);
    其他要执行的操作...;
    sem_post(semId_1);
    
    子进程:
    sem_wait(semId_1);
    其他要执行的操作...;
    sem_post(semId_1);
    
(3). sem_close(semId_1);                            ---关闭semId

(4). sem_unlink("sem_1");                           ---卸载sem_1

2> 同步(sync)
(1). sem_t *semId_1 = sem_open("sem_1", O_CREAT, 0666, 1);           
    sem_t *semId_2 = sem_open("sem_2", O_CREAT, 0666, 0);
    
    sem_init(semId_1, 1, 1);                        ---初始化semId, 第二个参数为 0 时,在进程与线程间通信, 第二个参数非 0 时,在进程与进程间通信,第三个参数是 arg.val的值
    sem_init(semId_2, 1, 0);

(2).sem_getvalue(semId_1,&val1);                    ---获取arg.val
    sem_getvalue(semId_2,&val2);

    父进程:
    sem_wait(semId_1);
    其他要执行的操作...;
    sem_post(semId_2);
    
    子进程:
    sem_wait(semId_2);
    其他要执行的操作...;
    sem_post(semId_1);
    
(3). sem_close(semId_1);                          
    sem_close(semId_2);

(4). sem_unlink("sem_1");                         
    sem_unlink("sem_2");
    
    
僵尸进程处理
(1)//singal(SIGCHLD, SIG_IGN);    //忽略子进程结束发给父进程的SIGCHLD信号

(2)signal(SIGCHLD, sigchld_handler);

void sigchld_handler(int sig)
{
    //wait(NULL);        //只能处理一个进程
    while(waitpid(-1, NULL, WNOHANG) > 0)        //推荐:处理所有进程
        ;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值