亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C語(yǔ)言中進(jìn)程間通訊的方式詳解

 更新時(shí)間:2022年08月18日 15:45:10   作者:lhb2998658795  
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言中幾種進(jìn)程間通訊的方式,文中的示例代碼講解詳細(xì),?對(duì)我們學(xué)習(xí)或工作有一定的借鑒價(jià)值,需要的可以參考一下

一.無(wú)名管道

1.1無(wú)名管道的原理

無(wú)名管道只能用于親緣間進(jìn)程的通信,無(wú)名管道的大小是64K。無(wú)名管道是內(nèi)核空間實(shí)現(xiàn)的機(jī)制。

1.2功能

1) Pipe()創(chuàng)建一個(gè)管道,這是一個(gè)單向的數(shù)據(jù)通道,可用于進(jìn)程間通信。

2)數(shù)組pipefd用于返回兩個(gè)指向管道末端的文件描述符。

3)Pipefd[0]指的是管道的讀端。Pipefd[1]指的是管道的寫(xiě)入端,寫(xiě)入管道的寫(xiě)入端數(shù)據(jù)由內(nèi)核進(jìn)行緩沖(64k),直到從管道的讀取端讀取為止。

1.3無(wú)名管道通信特點(diǎn)

1.只能用于親緣間進(jìn)程的通信

2.無(wú)名管道數(shù)據(jù)半雙工的通信的方式

單工 : A -------------->B

半雙工 : 同一時(shí)刻 A----->B B------>A

全雙工 : 同一時(shí)刻 A<---->B

3.無(wú)名管道的大小是64K

4.無(wú)名管道不能夠使用lseek函數(shù)

5.讀寫(xiě)的特點(diǎn)

如果讀端存在寫(xiě)管道:有多少寫(xiě)多少,直到寫(xiě)滿(mǎn)為止(64k)寫(xiě)阻塞

如果讀端不存寫(xiě)管道,管道破裂(SIGPIPE) (可以通過(guò)gdb調(diào)試看現(xiàn)象)

如果寫(xiě)端存在讀管道:有多少讀多少,沒(méi)有數(shù)據(jù)的時(shí)候阻塞等待

如果寫(xiě)端不存在讀管道:有多少讀多少,沒(méi)有數(shù)據(jù)的時(shí)候立即返回

1.4無(wú)名管道的實(shí)例

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h> 
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#define ERROR(msg) do{\
    printf("%s %s %d\n", __FILE__, __func__, __LINE__);\
    printf(msg);\
    exit(-1); \
}while(0)
 
int main(int argc, char const *argv[])
{
    pid_t pid;
    int num[2];
    char buff[128] = {0};
 
    if (pipe(num)){
        ERROR("pipe error");
    }
 
    if ((pid = fork()) == -1){
        ERROR("fork error");
    }else if(pid == 0){
        close(num[0]);
        while (1){
            memset(buff, 0, sizeof(buff));
            printf("請(qǐng)輸入您要輸入的數(shù)值>>");
            fgets(buff, sizeof(buff), stdin);
            buff[strlen(buff) -1] = '\0';
            write(num[1], buff, strlen(buff));
 
            if (!strncmp(buff, "quit", 4)){
                break;
            }
 
        }
        close(num[1]);
        exit(EXIT_SUCCESS);
    }else{
        close(num[1]);
        while (1){
            memset(buff, 0, sizeof(buff));
            read(num[0], buff, sizeof(buff));
 
            if (!strncmp(buff, "quit", 4)){
                break;
            }
            printf("%s\n",buff);
        }   
        close(num[0]);
        wait(NULL);
    }
 
    return 0;
}

二.有名管道

2.1有名管道的原理

1)可以用于親緣間進(jìn)程的通信,也可以用于非親緣間的進(jìn)程的通信。

2)有名管道會(huì)創(chuàng)建一個(gè)文件,需要通信的進(jìn)程打開(kāi)這個(gè)文件,產(chǎn)生文件描述符后就可以通信了,有名管道的文件存在內(nèi)存上。

3)有名管道的大小也是64K,也不能使用lseek函數(shù)

2.2有名管道的特點(diǎn)

1.可以用于任意進(jìn)程間的通信

2.有名管道數(shù)據(jù)半雙工的通信的方式

3.有名管道的大小是64K

4.有名管道不能夠使用lseek函數(shù)

5.讀寫(xiě)的特點(diǎn)

如果讀端存在寫(xiě)管道:有多少寫(xiě)多少,直到寫(xiě)滿(mǎn)為止(64k)寫(xiě)阻塞

如果讀端不存寫(xiě)管道

1.讀權(quán)限沒(méi)有打開(kāi),寫(xiě)端在open的位置阻塞

2.讀端打開(kāi)后關(guān)閉,管道破裂(SIGPIPE) (可以通過(guò)gdb調(diào)試看現(xiàn)象)

如果寫(xiě)端存在讀管道:有多少讀多少,沒(méi)有數(shù)據(jù)的時(shí)候阻塞等待

如果寫(xiě)端不存在讀管道

1.寫(xiě)權(quán)限沒(méi)有打開(kāi),讀端在open的位置阻塞

2.寫(xiě)端打開(kāi)后關(guān)閉,有多少讀多少,沒(méi)有數(shù)據(jù)的時(shí)候立即返回

2.3有名管道實(shí)例

mkfifo文件:

#include <stdio.h>
#include <stdlib.h>
#define ERROR(msg) do{\
    printf("%s %s %d\n", __FILE__, __func__, __LINE__);\
    printf(msg);\
    exit(-1); \
}while(0)
 
int main(int argc, char const *argv[])
{
    if (mkfifo("./fifo",0666)){
        ERROR("mkfifo error");
    }
 
    //有名管道沒(méi)有阻塞,手動(dòng)加一個(gè)阻塞
    getchar();
 
    system("rm ./fifo -rf");
    
    return 0;
}

write文件:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
 
#define ERROR(msg) do{\
    printf("%s %s %d\n", __FILE__, __func__, __LINE__);\
    printf(msg);\
    exit(-1); \
}while(0)
 
int main(int argc, char const *argv[])
{
    int fd;
    char buff[128] = {0};
    if ((fd = open("./fifo",O_WRONLY)) == -1){
        ERROR("open fifo error\n");
    }
 
    while(1){
        printf("input >");
        fgets(buff, sizeof(buff), stdin);
        buff[strlen(buff) - 1] = '\0';
 
        write(fd, buff, strlen(buff));
        if(!strncmp("quit",buff,4))break;
    }
    close(fd);
    return 0;
}

read文件:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
 
#define ERROR(msg)                                          \
    do                                                      \
    {                                                       \
        printf("%s %s %d\n", __FILE__, __func__, __LINE__); \
        printf(msg);                                        \
        exit(-1);                                           \
    } while (0)
 
int main(int argc, char const *argv[])
{
    int fd;
    char buff[128] = {0};
    if ((fd = open("./fifo", O_RDONLY)) == -1)
    {
        ERROR("open error");
    }
 
    while (1){
        memset(buff, 0, sizeof(buff));
        read(fd, buff, sizeof(buff));
        if (!strncmp("quit",buff,4)){
            break;
        }
 
        printf("%s\n",buff);
    }
    close(fd);
    return 0;
}

三.信號(hào)

3.1信號(hào)的概念

信號(hào)是中斷的一種軟件模擬,中斷是基于硬件實(shí)現(xiàn)的,信號(hào)是基于linux內(nèi)核實(shí)現(xiàn)的。

用戶(hù)可以給進(jìn)程發(fā)信號(hào),進(jìn)程可以給進(jìn)程發(fā)信號(hào),內(nèi)核也可以給進(jìn)程發(fā)信號(hào)。進(jìn)程對(duì)

信號(hào)的處理方式有三種:捕捉,忽略,默認(rèn)

3.2發(fā)送信號(hào)的函數(shù)

int raise(int sig);

功能:給自己(進(jìn)程或者線程)發(fā)信號(hào)

參數(shù):

@sig:信號(hào)號(hào)

返回值:成功返回0,失敗返回非0

int kill(pid_t pid, int sig);

功能:給進(jìn)程發(fā)信號(hào)

參數(shù):

@pid:進(jìn)程號(hào)

  • pid > 0 :給pid對(duì)應(yīng)的進(jìn)程發(fā)信號(hào)
  • pid = 0 :給同組的進(jìn)程發(fā)信號(hào)
  • pid = -1:給所有的有權(quán)限操作的進(jìn)程發(fā)送信號(hào),init進(jìn)程除外
  • pid < -1:給-pid對(duì)應(yīng)的同組的進(jìn)程發(fā)信號(hào)       

@sig:信號(hào)號(hào)

返回值:成功返回0,失敗返回-1置位錯(cuò)誤碼  

3.3常用的信號(hào)

1.在上述的信號(hào)中只有SIGKILL和SIGSTOP兩個(gè)信號(hào)不能被捕捉也不能被忽略

2.SIGCHLD,當(dāng)子進(jìn)程結(jié)束的時(shí)候,父進(jìn)程收到這個(gè)SIGCHLD的信號(hào)

3.4實(shí)例

捕捉ctrl+c

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#define ERROR(msg) do{\
    printf("%s %s %d\n", __FILE__, __func__, __LINE__);\
    printf(msg);\
    exit(-1); \
}while(0)
 
void handle(int num)
{
    if (num == SIGINT){
        printf("我收到一個(gè)ctrl+c的信號(hào)\n");
    }
}
 
int main(int argc, char const *argv[])
{
    //捕捉
    if (signal(SIGINT, handle) == SIG_ERR){
        ERROR("register signal error");
    }
    //忽略
    if (signal(SIGINT,SIG_IGN) == SIG_ERR){
        ERROR("register signal error");
    }
    //默認(rèn)
    if (signal(SIGINT,SIG_DFL) == SIG_ERR){
        ERROR("register signale");
    }
 
 
    while(1);
    return 0;
}

捕捉管道破裂的消息

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
 
#define ERROR(msg) do{\
    printf("%s %s %d\n", __FILE__, __func__, __LINE__);\
    printf(msg);\
    exit(-1); \
}while(0)
 
void handle(int num)
{
    if (num == SIGPIPE){
        printf("捕捉到一條管道破裂的消息\n");
    }
}
 
int main(int argc, char const *argv[])
{
    int num[2];
    char buff[32] = "123";
 
    if(pipe(num)){
        ERROR("pipe error");
    }
 
    if (signal(SIGPIPE,handle) == SIG_ERR){
        ERROR("signal error");
    }
 
    close(num[0]);
 
    write(num[1],buff,strlen(buff));
    return 0;
}

阻塞等待為子進(jìn)程回收資源

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
 
void signal_handle(int signo)
{
    printf("我是父進(jìn)程,收到了子進(jìn)程退出的信號(hào),為它回收資源\n");
    waitpid(-1,NULL,WNOHANG); //非阻塞方式回收資源
    printf("為子進(jìn)程回收資源成功\n");
    raise(SIGKILL);  //給父進(jìn)程發(fā)送信號(hào),結(jié)束父進(jìn)程
}
 
int main(int argc,const char * argv[])
{
    pid_t pid;
 
    pid = fork();
    if(pid == -1){
        ERROR("fork error");
    }else if(pid == 0){
        sleep(5);
        printf("子進(jìn)程執(zhí)行結(jié)束了\n");
        exit(EXIT_SUCCESS);
    }else{
        if(signal(SIGCHLD,signal_handle)==SIG_ERR)
            ERROR("signal error");
 
        while(1);
    }
    
    return 0;
}

用arlarm實(shí)現(xiàn)一個(gè)斗地主機(jī)制

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
 
#define ERROR(msg) do{\
    printf("%s %s %d\n", __FILE__, __func__, __LINE__);\
    printf(msg);\
    exit(-1); \
}while(0)
 
void handle(int num)
{
    if (num == SIGALRM){
        printf("自動(dòng)出牌\n");
    }
    alarm(3);
}
 
int main(int argc, char const *argv[])
{
    char ch;
    if (signal(SIGALRM,handle) == SIG_ERR){
        ERROR("signale error");
    }
    
    alarm(3);
 
    while (1){
        printf("請(qǐng)輸入您要出的牌>>");
        ch = getchar();
        getchar();
        printf("%c\n",ch);
        alarm(3);
    }
    return 0;
}

四.IPC進(jìn)程間通信

4.1IPC進(jìn)程間通信的種類(lèi)

(1)消息隊(duì)列

(2)共享內(nèi)存

(3)信號(hào)燈集

4.2查看IPC進(jìn)程間通信的命令

4.2.1查看

ipcs -q //查看消息隊(duì)列的命令

ipcs -m //查看共享內(nèi)存的命令

ipcs -s //查看信號(hào)燈集的命令

4.2.2刪除ipc的命令

ipcrm -q msqid //刪除消息隊(duì)列命令

ipcrm -m shmid //刪除共享內(nèi)存命令

ipcrm -s semid //刪除信號(hào)燈集的命令

4.3消息隊(duì)列

4.3.1消息隊(duì)列的原理

消息隊(duì)列也是借助內(nèi)核實(shí)現(xiàn)的,A進(jìn)程將消息放到消息隊(duì)列中,隊(duì)列中的消息

有消息的類(lèi)型和消息的正文。B進(jìn)程可以根據(jù)想取的消息的類(lèi)型從消息隊(duì)列中

將消息讀走。消息隊(duì)列默認(rèn)的大小是16384個(gè)字節(jié)。如果消息隊(duì)列中的消息滿(mǎn)了,

A進(jìn)程還想往隊(duì)列中發(fā)消息,此時(shí)A進(jìn)程阻塞。

4.3.2IPC進(jìn)程間通信鍵值的獲取

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
 
#define ERROR(msg) do{\
    printf("%s %s %d\n", __FILE__, __func__, __LINE__);\
    printf(msg);\
    exit(-1); \
}while(0)
 
int main(int argc, char const *argv[])
{
    key_t key;
    struct stat st;
 
   if ((key = ftok("/home/linux",'w')) == -1){
        ERROR("ftok error");
   }
 
   printf("key=%#x\n",key);
 
   if (stat("/home/linux",&st)){
        ERROR("stat error");
   }
 
   printf("pro_id=%#x,devno=%#lx,ino=#=%#lx\n",'w',st.st_dev,st.st_ino);
    return 0;
}

結(jié)果圖:

4.3.3消息隊(duì)列的實(shí)例:(不關(guān)注類(lèi)型的)

頭文件:

#ifndef __MYHEAD_H__
#define __MYHEAD_H__
 
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/msg.h>
#include <string.h>
 
#define  PRINT_ERR(msg) do{\
    printf("%s %s %d\n", __FILE__, __func__, __LINE__);\
    printf(msg);\
    exit(-1); \
}while(0)
 
 
#define MSGSIZE (sizeof(msg_t)-sizeof(long))
 
typedef  struct mubuf{
    long mtype;
    char text[512];
}msg_t;
 
#endif

發(fā)送方:

#include "myhead.h"
 
int main(int argc, char const *argv[])
{
    key_t key;
    int msqid;
    msg_t msg ={
        .mtype = 100,
    };
 
     if((key = ftok("/home/linux/",'r'))==-1)
        PRINT_ERR("ftok get key error");
 
    if((msqid = msgget(key,IPC_CREAT|0666))==-1)
        PRINT_ERR("create msg queue error");
 
    while (1){
        memset(msg.text,0,sizeof(msg.text));
        fgets(msg.text,MSGSIZE,stdin);
        msg.text[strlen(msg.text) - 1] = '\0';
 
        msgsnd(msqid, &msg, MSGSIZE, 0);
 
        if (!strncmp(msg.text,"quit",4)){
            break;
        }
    }
 
    msgctl(msqid, IPC_RMID, NULL);
    return 0;
}

接受方:

#include "myhead.h"
 
int main(int argc, char const *argv[])
{
    key_t key;
    int msgqid;
    msg_t msg;
 
    if ((key = ftok("/home/linux",'r')) == -1){
        PRINT_ERR("ftok error");
    }
 
    if ((msgqid = msgget(key, IPC_CREAT|0666)) == -1){
        PRINT_ERR("msgget error");
    }
 
    while (1){
        memset(msg.text, 0, sizeof(msg.text));
        msgrcv(msgqid, &msg, MSGSIZE,0,0);
 
        if (!strncmp("quit",msg.text,4)){
            break;
        }
 
        printf("%s\n",msg.text);
    }
 
    msgctl(msgqid,IPC_RMID,NULL);
    return 0;
}

4.3.4消息隊(duì)列的實(shí)例:(關(guān)注類(lèi)型的)

頭文件:

#ifndef __MSGQUE_H__
#define __MSGQUE_H__
 
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/msg.h>
#include <string.h>
 
typedef struct msgbuf {
    long id;
    char name[30];
    char sex;
    int age;
}msg_t;
 
#define MSGSIZE (sizeof(msg_t)-sizeof(long))
 
#endif

發(fā)送方:

#include "msgqueue.h"
#include <head.h>
 
int main(int argc, const char* argv[])
{
    key_t key;
    int msqid;
 
    if ((key = ftok("/home/linux/", 'r')) == -1)
        PRINT_ERR("ftok get key error");
 
    if ((msqid = msgget(key, IPC_CREAT | 0666)) == -1)
        PRINT_ERR("create msg queue error");
 
    msg_t m1 = {
        .id = 1,
        .name = "zhangsan",
        .sex = 'm',
        .age = 30,
    };
    msgsnd(msqid, &m1, MSGSIZE, 0);
    msg_t m2 = {
        .id = 2,
        .name = "lisi",
        .sex = 'w',
        .age = 18,
    };
    msgsnd(msqid, &m2, MSGSIZE, 0);
    msg_t m3 = {
        .id = 3,
        .name = "wangwu",
        .sex = 'm',
        .age = 22,
    };
    msgsnd(msqid, &m3, MSGSIZE, 0);
 
 
    // msgctl(msqid, IPC_RMID, NULL);
 
    return 0;
}

接受方:

#include "msgqueue.h"
 
int main(int argc, const char* argv[])
{
    key_t key;
    int msqid;
    msg_t msg;
 
 
    if ((key = ftok("/home/linux/", 'r')) == -1)
        PRINT_ERR("ftok get key error");
 
    if ((msqid = msgget(key, IPC_CREAT | 0666)) == -1)
        PRINT_ERR("create msg queue error");
 
 
    memset(&msg, 0, sizeof msg);
    msgrcv(msqid, &msg, MSGSIZE, atoi(argv[1]), 0);
    printf("id=%ld,name=%s,sec=%c,age=%d\n",msg.id,msg.name,msg.sex,msg.age);
 
    // msgctl(msqid, IPC_RMID, NULL);
 
    return 0;
}

結(jié)果圖:

4.4共享內(nèi)存

4.4.1原理:

共享內(nèi)存:在內(nèi)核空間創(chuàng)建共享內(nèi)存,讓用戶(hù)的A和B進(jìn)程都能夠訪問(wèn)到。通過(guò)這塊內(nèi)存

進(jìn)行數(shù)據(jù)的傳遞。共享內(nèi)存所有的進(jìn)程間通信中效率最高的方式(不需要來(lái)回拷貝數(shù)據(jù)),共享內(nèi)存的大小為 4k整數(shù)倍。

4.4.2實(shí)例

接受方:

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <stdlib.h>
 
#define  PRINT_ERR(msg) do{\
    printf("%s %s %d\n", __FILE__, __func__, __LINE__);\
    printf(msg);\
    exit(-1); \
}while(0)
 
int main(int argc, char const *argv[])
{
    key_t key;
    int shmid;
    char* over;
 
    if ((key = ftok("/home/linux", 'r')) == -1){
        PRINT_ERR("ftok error");
    }
 
    if ((shmid = shmget(key, 4096, IPC_CREAT|0666)) == -1){
        PRINT_ERR("shemget error");
    }
 
    if ((over = shmat(shmid, NULL, 0)) == (void*)-1){
        PRINT_ERR("shmat error");
    }
 
    while (1){
        if (!strncmp("quit", over, 4))break;
        getchar();
 
        printf("%s\n",over);
    }
 
    if (shmdt(over)){
        PRINT_ERR("shmdt error");
    }
 
    shmctl(shmid,IPC_RMID,NULL);
    return 0;
}

發(fā)送方:

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <stdlib.h>
 
#define  PRINT_ERR(msg) do{\
    printf("%s %s %d\n", __FILE__, __func__, __LINE__);\
    printf(msg);\
    exit(-1); \
}while(0)
 
int main(int argc, char const *argv[])
{
    key_t key;
    int shmid;
    char* over;
 
    if ((key = ftok("/home/linux", 'r')) == -1){
        PRINT_ERR("ftok error");
    }
 
    if ((shmid = shmget(key, 4096, IPC_CREAT|0666)) == -1){
        PRINT_ERR("shmget error\n");
    }
 
    if ((over = shmat(shmid, NULL, 0)) == (void*)-1){
        PRINT_ERR("shmat error\n");
    }
 
    while (1){
        printf("請(qǐng)輸入>>");
        fgets(over,4096,stdin);
        over[strlen(over) - 1] = '\0';
 
        if (!strncmp("quit",over,4)){
            break;
        }
    }
 
    if (shmdt(over)){
        PRINT_ERR("shmdt error\n");
    }
 
    shmctl(shmid,IPC_RMID,NULL);
    return 0;
}

4.5信號(hào)燈集合

信號(hào)量的原理

信號(hào)量:又叫信號(hào)燈集,它是實(shí)現(xiàn)進(jìn)程間同步的機(jī)制。在一個(gè)信號(hào)燈集中可以有很多的信號(hào)燈,這些信號(hào)燈它們的工作相關(guān)不干擾。一般使用的時(shí)候使用的是二值信號(hào)燈。

信號(hào)燈集函數(shù)的封裝

sem.h

#ifndef __SEM_H__
#define __SEM_H__
 
int mysem_init(int nsems);
int P(int semid, int semnum);
int V(int semid, int semnum);
int sem_del(int semid);
 
#endif
sem.c
#include <head.h>
 
union semun {
    int val; /* Value for SETVAL */
    struct semid_ds* buf; /* Buffer for IPC_STAT, IPC_SET */
};
 
int semnum_init_value(int semid, int which, int value)
{
    union semun sem = {
        .val = value,
    };
    if (semctl(semid, which, SETVAL, sem) == -1)
        PRINT_ERR("semctl int value error");
    return 0;
}
 
//初始化信號(hào)燈集
int mysem_init(int nsems)
{
    key_t key;
    int semid;
    // 1.通過(guò)ftok獲取鍵值
    if ((key = ftok("/home/linux/", 'g')) == -1)
        PRINT_ERR("get key error");
    // 2.如果不選擇就創(chuàng)建信號(hào)燈集,如果存在返回已存在的錯(cuò)誤
    if ((semid = semget(key, nsems, IPC_CREAT | IPC_EXCL | 0666)) == -1) {
        if (errno == EEXIST) {
            //如果已存在,這里調(diào)用semget,直接返回semid
            semid = semget(key, nsems, IPC_CREAT | 0666);
        } else {
            PRINT_ERR("create sem error");
        }
    } else {
        // 3.初始化信號(hào)燈集中的信號(hào)燈
        for (int i = 0; i < nsems; i++) {
            semnum_init_value(semid, i, !i);
        }
    }
 
    return semid;
}
 
//申請(qǐng)資源
int P(int semid, int semnum)
{
    struct sembuf buf = {
        .sem_num = semnum,
        .sem_op = -1,
        .sem_flg = 0,
    };
 
    if (semop(semid, &buf, 1))
        PRINT_ERR("request resource error");
 
    return 0;
}
//釋放資源
int V(int semid, int semnum)
{
    struct sembuf buf = {
        .sem_num = semnum,
        .sem_op = 1,
        .sem_flg = 0,
    };
 
    if (semop(semid, &buf, 1))
        PRINT_ERR("free resource error");
 
    return 0;
}
//刪除信號(hào)燈集
int sem_del(int semid)
{
    semctl(semid,0,IPC_RMID);
}

用信號(hào)燈集實(shí)現(xiàn)進(jìn)程同步

寫(xiě)端:

#include <head.h>
#include "sem.h"
 
int main(int argc, const char* argv[])
{
    key_t key;
    int shmid,semid;
    char* waddr;
    //0.信號(hào)量的初始化
    semid = mysem_init(2);
    if(semid == -1){
        printf("sem init error");
        return -1;
    }
    // 1.獲取key
    if ((key = ftok("/home/linux", 'p')) == -1)
        PRINT_ERR("get key error");
    // 2.創(chuàng)建共享內(nèi)存
    if ((shmid = shmget(key, 4096, IPC_CREAT | 0666)) == -1)
        PRINT_ERR("create share memory error");
    // 3.將共享內(nèi)存映射到用戶(hù)空間
    if ((waddr = shmat(shmid, NULL, 0)) == (void*)-1)
        PRINT_ERR("shmat error");
    printf("waddr = %p\n", waddr);
    // 4.寫(xiě)操作
    while (1) {
        P(semid,0);
        printf("input > ");
        fgets(waddr, 4096, stdin);
        waddr[strlen(waddr) - 1] = '\0';
        if (strncmp(waddr, "quit", 4) == 0)
            break;
        V(semid,1);
    }
    // 5.取消地址映射
    if (shmdt(waddr))
        PRINT_ERR("shmdt error");
 
    // 6.刪除共享內(nèi)存
    if (shmctl(shmid, IPC_RMID, NULL))
        PRINT_ERR("shmrm error");
    //7.刪除信號(hào)量
    sem_del(semid);
    return 0;
}

讀端口:

#include "sem.h"
#include <head.h>
int main(int argc, const char* argv[])
{
    key_t key;
    int shmid, semid;
    char* raddr;
    // 0.信號(hào)量的初始化
    semid = mysem_init(2);
    if (semid == -1) {
        printf("sem init error");
        return -1;
    }
    // 1.獲取key
    if ((key = ftok("/home/linux", 'p')) == -1)
        PRINT_ERR("get key error");
    // 2.創(chuàng)建共享內(nèi)存
    if ((shmid = shmget(key, 4096, IPC_CREAT | 0666)) == -1)
        PRINT_ERR("create share memory error");
 
    // 3.將共享內(nèi)存映射到用戶(hù)空間
    if ((raddr = shmat(shmid, NULL, 0)) == (void*)-1)
        PRINT_ERR("shmat error");
 
    printf("waddr = %p\n", raddr);
    // 4.讀操作
    while (1) {
        P(semid,1);
        printf("raddr = %s\n", raddr);
        if (strncmp(raddr, "quit", 4) == 0)
            break;
        V(semid,0);
    }
    // 5.取消地址映射
    if (shmdt(raddr))
        PRINT_ERR("shmdt error");
 
    // 6.刪除共享內(nèi)存
    shmctl(shmid, IPC_RMID, NULL);
 
    //7.刪除信號(hào)量
    sem_del(semid);
    return 0;
}

以上就是C語(yǔ)言中進(jìn)程間通訊的方式詳解的詳細(xì)內(nèi)容,更多關(guān)于C語(yǔ)言進(jìn)程通訊的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C語(yǔ)言如何改變字體顏色

    C語(yǔ)言如何改變字體顏色

    這篇文章主要介紹了C語(yǔ)言如何改變字體顏色,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • Matlab利用遺傳算法GA求解非連續(xù)函數(shù)問(wèn)題詳解

    Matlab利用遺傳算法GA求解非連續(xù)函數(shù)問(wèn)題詳解

    遺傳算法起源于對(duì)生物系統(tǒng)所進(jìn)行的計(jì)算機(jī)模擬研究。其本質(zhì)是一種高效、并行、全局搜索的方法,能在搜索過(guò)程中自動(dòng)獲取和積累有關(guān)搜索空間的知識(shí),并自適應(yīng)地控制搜索過(guò)程以求得最佳解。本文將利用其求解非連續(xù)函數(shù)問(wèn)題,需要的可以參考一下
    2022-09-09
  • C++中的變長(zhǎng)參數(shù)深入理解

    C++中的變長(zhǎng)參數(shù)深入理解

    變長(zhǎng)參數(shù)的函數(shù),即參數(shù)個(gè)數(shù)可變、參數(shù)類(lèi)型不定的函數(shù)。設(shè)計(jì)一個(gè)參數(shù)個(gè)數(shù)可變、參數(shù)類(lèi)型不定的函數(shù)是可能的,最常見(jiàn)的例子是printf函數(shù)、scanf函數(shù)和高級(jí)語(yǔ)言的Format函數(shù)。最近的一個(gè)項(xiàng)目中就遇到這么一個(gè)相關(guān)的問(wèn)題,感興趣的朋友們下面來(lái)一起看看吧。
    2016-10-10
  • C語(yǔ)言使用rand函數(shù)生成隨機(jī)數(shù)

    C語(yǔ)言使用rand函數(shù)生成隨機(jī)數(shù)

    這篇文章介紹了C語(yǔ)言使用rand函數(shù)生成隨機(jī)數(shù)的方法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-12-12
  • C語(yǔ)言全方位講解指針的使用

    C語(yǔ)言全方位講解指針的使用

    指針是C語(yǔ)言中一個(gè)非常重要的概念,也是C語(yǔ)言的特色之一。使用指針可以對(duì)復(fù)雜數(shù)據(jù)進(jìn)行處理,能對(duì)計(jì)算機(jī)的內(nèi)存分配進(jìn)行控制,在函數(shù)調(diào)用中使用指針還可以返回多個(gè)值
    2022-04-04
  • 使用Visual Studio 2010/2013編譯V8引擎步驟分享

    使用Visual Studio 2010/2013編譯V8引擎步驟分享

    這篇文章主要介紹了使用Visual Studio 2013編譯V8引擎步驟分享,需要的朋友可以參考下
    2015-08-08
  • 解決codeblocks斷點(diǎn)不停無(wú)效的問(wèn)題

    解決codeblocks斷點(diǎn)不停無(wú)效的問(wèn)題

    今天小編就為大家分享一篇解決codeblocks斷點(diǎn)不停無(wú)效的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-12-12
  • C++?自定義單向鏈表?ListNode詳情

    C++?自定義單向鏈表?ListNode詳情

    這篇文章主要介紹了C++?自定義單向鏈表?ListNode詳情,文章將介紹鏈表中不帶頭結(jié)點(diǎn),沒(méi)有存放鏈表長(zhǎng)度的節(jié)點(diǎn),從頭結(jié)點(diǎn)開(kāi)始就存放數(shù)據(jù)得一種,具有一定得參考價(jià)值,需要的小伙伴可以參考一下
    2022-03-03
  • C++實(shí)現(xiàn)KDTree 附完整代碼

    C++實(shí)現(xiàn)KDTree 附完整代碼

    這篇文章主要介紹了C++實(shí)現(xiàn)KDTree的代碼詳解,包括kdTree概念介紹及分割的作用,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-07-07
  • Qt編寫(xiě)地圖遷徙圖的實(shí)現(xiàn)示例

    Qt編寫(xiě)地圖遷徙圖的實(shí)現(xiàn)示例

    本文主要介紹了Qt編寫(xiě)地圖遷徙圖的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-12-12

最新評(píng)論