Linux c/c++之IPC进程间通信

简介: 这篇文章详细介绍了Linux下C/C++进程间通信(IPC)的三种主要技术:共享内存、消息队列和信号量,包括它们的编程模型、API函数原型、优势与缺点,并通过示例代码展示了它们的创建、使用和管理方法。

1. IPC定义

IPC技术: 内核进程通信(Inter Process Communication)

2. 共享内存

2.1 共享内存定义

    shm(share memory),在主机上指定一块内存作为进程之间的共享内存, 不同的进程之间可以通过一些方式去访问这块内存。

2.2 shm(共享内存 编程模型)

  1. 创建key ftok函数
  2. 创建共享内存 shmget函数
  3. 挂载共享内存 shmat函数
  4. 卸载共享内存 shmdt函数
  5. 删除共享内存 shmctl函数

2.3 shm的一些函数原型

2.3.1 ftok函数

//头文件
#include <sys/types.h>
#include <sys/ipc.h>
//函数原型
key_t ftok(const char *pathname, int proj_id);

//返回值: 返回值为一个4byte的整数(返回-1失败)
//0--15  bit: pathname的st_ino属性的低16位
//16--23 bit: pathname的st_dev属性的低8位
//24--31 bit: pro_id的低8位

//参数一: 传入一个路径,一般使用当前路径"."
//参数二: 任意的一个整数,因为要做进程间通信,
//那么另一个进程需要与这个数保持一致才能找到对应的ipcid,一般只使用8个bit,因此取值范围在0--255

2.3.2 shmget函数

//头文件
#include <sys/ipc.h>
#include <sys/shm.h>
//函数原型
int shmget(key_t key, size_t size, int shmflg);

//返回值: 返回一个整数(返回-1失败) 

//参数一: ftok函数的返回值
//参数二: 共享的内存大小(byte)(如果数值为1 -- 4096,实际申请4k(一页))
//参数三: 主要与一些标志有关
// IPC_CREAT  不存在共享内存就创建,否则打开
// IPC_EXCL   不存在共享内存才创建,否则错误

2.3.3 shmat函数

//头文件
#include <sys/types.h>
#include <sys/shm.h>
//函数原型
void *shmat(int shmid, const void *shmaddr, int shmflg);

//返回值: 返回申请的共享内存的首地址(返回-1则挂载失败)

//参数一: shmget函数的返回值
//参数二: 一般为0,表示连接到一个由内核选择的可用地址之上
//参数三: 一般为0

2.3.4 shmdt函数

//头文件
#include <sys/types.h>
#include <sys/shm.h>
//函数原型
int shmdt(const void *shmaddr);

//返回值: 成功返回0,失败返回-1
//参数一: shmat函数的返回值

2.3.5 shmctl函数

//头文件
#include <sys/ipc.h>
#include <sys/shm.h>
//函数原型
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

//返回值: 失败返回-1,
//参数一: shmget函数的返回值
//参数二: 设置调用者对共享内存段的权限
// IPC_STAT: 调用者必须对共享内存具有读权限
// IPC_SET: 对shmid_ds 中的某些值做一些修改
// IPC_RMID: 表示销毁某个段
// IPC_INFO: 返回共享内存限制和参数的信息
// SHM_INFO: 返回一个shm_info的结构体
// SHM_STAT: 返回该内存段在内核数组的索引,该数组记录所有共享内存段的信息
// SHM_LOCK: 防止交换共享内存段
// SHM_UNLOCK: 解除防止交换共享内存段
//参数三: 一个指向shmid_ds的结构体指针
struct shmid_ds 
{   struct ipc_perm shm_perm;/*用户权限*/
    size_t shm_segsz;/* segment (bytes)的大小*/
    time_t shm_atime;/*最后连接时间*/
    time_t shm_dtime;/*最后的分离时间时间*/
    time_t ctime;/*上次更改时间*/
    pid_t  shm_cpid;/*创建器的PID*/
    ......
};

2.4 共享内存的优势与缺点

2.4.1 优势

因为两个进程可以使用一段内存, 这就构成了进程之间的双向通信, 无疑传输速率是很快的, 是最快的进程间通信方式。因为不同的进程之间是直接从这一段内存之中存放、读取数据。而且使用共享内存进行通信对数据是没有什么限制的。并且共享内存的生命周期与系统内核的生命周期是一致的。

2.4.2 缺点

共享内存并没有提供同步机制,在一个进程对共享内存进行写操作结束之前,另一个进程是不能对这块共享内存进行同步访问的,因为我们通常想要实现的是多个进程对共享内存的同步访问。

2.5 共享内存示例

使用shmA.c从共享内存中读取数据, shmB.c向共享内存中写入数据, shmctl.c删除共享内存段

2.5.1 共享内存数据读取端

//shmA.c  读取端
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <signal.h>

int* p = NULL;
void hand(){
    //5.卸载功能共享内存
    shmdt(p);
    printf("bye bye!\n");

    exit(0);
}
int main(){
    signal(SIGINT,hand);
    //1.创建key
    key_t key = ftok(".",'m');  //参数二在256之内
    if(-1 == key) printf("create key error:%m\n"),exit(-1);
    printf("create key success!\n");
    //2.创建共享内存   内存单位之页   1页 == 4k
    int shmid = shmget(key,4096,IPC_CREAT);
    if(-1 == shmid) printf("shmget error:%m\n"),exit(-1);
    printf("shmget success!\n");
    //3.挂载共享内存
    p = (int*)shmat(shmid,NULL,0);
    if((int*)-1 == p) printf("shmat error:%m\n"),exit(-1);
    printf("shmat success!\n");
    //4.使用共享内存
    while(1){
        printf("%d\n",*p);
        sleep(1);
    }

    return 0;
}

2.5.2 共享内存数据发送端

//shmB.c  写入端
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <signal.h>

int* p = NULL;
void hand(){
    //5.卸载功能共享内存
    shmdt(p);
    printf("bye bye!\n");

    exit(0);
}
int main(){
    signal(SIGINT,hand);
    //1.创建key
    key_t key = ftok(".",'m');  //参数二在256之内
    if(-1 == key) printf("create key error:%m\n"),exit(-1);
    printf("create key success!\n");
    //2.获取共享内存  
    int shmid = shmget(key,4096,IPC_CREAT);
    if(-1 == shmid) printf("shmget error:%m\n"),exit(-1);
    printf("shmget success!\n");
    //3.挂载共享内存
    p = (int*)shmat(shmid,NULL,0);
    if(NULL == p) printf("shmat error:%m\n"),exit(-1);
    printf("shmat success!\n");
    //4.使用共享内存
    int n = 0;
    while(1){
        *p = n++;
        sleep(1);
    }

    return 0;
}

2.5.3 共享内存段删除端

//shmctl.c  删除共享内存
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int main(){
    //1.创建key
    key_t key = ftok(".",'m');  //参数二在256之内
    if(-1 == key) printf("create key error:%m\n"),exit(-1);
    printf("create key success!\n");
    //2.获取共享内存  
    int shmid = shmget(key,4096,IPC_CREAT);
    if(-1 == shmid) printf("shmget error:%m\n"),exit(-1);
    printf("shmget success!\n");

    //3.删除共享内存
    shmctl(shmid,IPC_RMID,NULL);

    return 0;
}

2.5.4 运行结果

shmA读取数据进程端单独运行:

shmA读取数据进程端与shmB写入数据进程端同时运行:

ipcs -m 命令查看当前共享内存信息:

使用shmctl删除当前创建的共享内存段后:

3. 消息队列

3.1 消息队列定义

    msg(message queue), 在主机上指定一个或者多个队列, 一方进程向队列之中放数据, 另一方从队列之中拿东西。

3.2 msg(消息队列 编程模型)

  1. 创建key ftok函数
  2. 创建消息队列 msgget函数
  3. 收发消息 msgrcv 函数 msgsnd 函数
  4. 删除消息队列 msgctl函数

3.3 msg的一些函数原型

3.3.1 ftok函数

//头文件
#include <sys/types.h>
#include <sys/ipc.h>
//函数原型
key_t ftok(const char *pathname, int proj_id);

//返回值: 返回值为一个4byte的整数(返回-1失败)
//0--15  bit: pathname的st_ino属性的低16位
//16--23 bit: pathname的st_dev属性的低8位
//24--31 bit: pro_id的低8位

//参数一: 传入一个路径,一般使用当前路径"."
//参数二: 任意的一个整数,因为要做进程间通信,
//那么另一个进程需要与这个数保持一致才能找到对应的ipcid,一般只使用8个bit,因此取值范围在0--255

3.3.2 msgget函数

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

int msgget(key_t key, int msgflg);

//返回值: 返回一个整数(-1表示失败)
//参数一: ftok函数的返回值
//参数二: 主要是一些标志
// IPC_CREAT  不存在共享内存就创建,否则打开
// IPC_EXCL   不存在共享内存才创建,否则错误

3.3.3 msgrcv函数

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

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

//返回值: (失败返回-1)返回实际复制到mtext数组中的字节数
//参数一: msgget函数的返回值
//参数二: 指向消息缓冲区的指针,此位置用来暂时存储发送和接收的消息,是一个用户可定义的通用结构
    struct msgbuf {
        long mtype;    
        char mtext[1];  //可以是1,也可以是其它数
    };
//参数三: 消息的大小
//参数四: 从消息队列内读取的消息形态。如果值为零,则表示消息队列中的所有消息都会被读取。
//参数五: 用来指明核心程序在队列没有数据的情况下所应采取的行动。如果msgflg和常数IPC_NOWAIT合用,则在消息队列呈空时,不做等待马上返回-1,并设定错误码为ENOMSG。

3.3.4 msgsnd函数

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

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

//返回值: (失败返回-1)成功返回0
//参数一: msgget函数的返回值
//参数二: 指向消息缓冲区的指针,此位置用来暂时存储发送和接收的消息,是一个用户可定义的通用结构
    struct msgbuf {
        long mtype;    
        char mtext[1];  //可以是1,也可以是其它数
    };
//参数三: 消息的大小
//参数四: 用来指明核心程序在队列没有数据的情况下所应采取的行动。如果msgflg和常数IPC_NOWAIT合用,则在msgsnd()执行时若是消息队列已满,则msgsnd()将不会阻塞,而会立即返回-1。当msgflg为0时,msgsnd()及msgrcv()在队列呈满或呈空的情形时,采取阻塞等待的处理模式。

3.3.5 msgctl函数

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

int msgctl(int msqid, int cmd, struct msqid_ds *buf);

//返回值: 失败返回-1,
//参数一: shmget函数的返回值
//参数二: 设置调用者对共享内存段的权限
// IPC_STAT: 调用者必须对共享内存具有读权限
// IPC_SET: 对msqid_ds 中的某些值做一些修改
// IPC_RMID: 表示销毁某个段
// IPC_INFO: 返回共享内存限制和参数的信息
// MSG_INFO: 返回一个msginfo的结构体
// MSG_STAT: 返回该内存段在内核数组的索引,该数组记录所有共享内存段的信息
//参数三: 一个指向msqid_ds 的结构体指针
struct msqid_ds {
               struct ipc_perm msg_perm;     /* 所有权和权限 */
               time_t          msg_stime;    /* 最后一次 msgsnd(2) */
               time_t          msg_rtime;    /* 最后一次 msgrcv(2) */
               time_t          msg_ctime;    /* 最后一次修改的时间*/
               unsigned long   __msg_cbytes; /* 当前队列的字节数(非标准) */
               msgqnum_t       msg_qnum;     /* 当前队列中的消息数 */
               msglen_t        msg_qbytes;   /* 队列允许的最大字节数 */
               pid_t           msg_lspid;    /* 上一次 msgsnd(2) 的PID*/
               pid_t           msg_lrpid;    /* PID of last msgrcv(2) */
           };

3.4 消息队列的优势与缺点

3.4.1 优势

消息队列提供了一种从进程向另一个进程发送一个数据块的方法。每个数据块都被认为是一个类型,接收进程接收的数据块可以有不同的类型值。可以通过发送消息来避免命名管道的同步和阻塞的问题。消息队列与管道不同的是,消息队列是基于消息的,而管道是基于字节流的,且消息队列的读取不一定是先入先出。

3.4.2 缺点

每个数据块有大小限制, 整个操作系统中所有的数据块总大小也有一个限制。

3.5 消息队列演示

3.5.1 消息发送端

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

//发送端进程
struct msgbuf{
    long type;
    char buff[20];
};
int main(){
    struct msgbuf msg;
    //1.创建key
    key_t key = ftok(".",'q');
    if(-1 == key) printf("ftok error:%m\n"),exit(-1);
    printf("ftok success!\n");
    //2. 创建消息队列
    int msgid = msgget(key,IPC_CREAT | 0666);
    if(-1 == msgid) printf("msgget error:%m\n"),exit(-1);
    printf("msgget success!\n");
    //3. 发消息
    int r;
    while(1){
        printf("请输入消息类型:");
        scanf("%ld",&msg.type);
        printf("请输入消息内容:");
        scanf("%s",msg.buff);
        r = msgsnd(msgid,&msg,sizeof(msg),IPC_NOWAIT); //IPC_NOWAIT非阻塞方式
        printf("r: %d\n",r);
    }


    return 0;
}

3.5.2 消息接收端

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

#define TYPE 2
//接收端进程
struct msgbuf{
    long type;
    char buff[20];
};
int main(){
    struct msgbuf msg;
    msg.type = TYPE;
    //1.创建key
    key_t key = ftok(".",'q');
    if(-1 == key) printf("ftok error:%m\n"),exit(-1);
    printf("ftok success!\n");
    //2. 创建消息队列
    int msgid = msgget(key,IPC_CREAT | 0666);
    if(-1 == msgid) printf("msgget error:%m\n"),exit(-1);
    printf("msgget success!\n");
    //3. 接收消息
    int r;
    while(1){
        memset(msg.buff,0,20);
        r = msgrcv(msgid,&msg,sizeof(msg),TYPE,IPC_NOWAIT);
        printf("r:%d msg:%s type:%ld\n", r, msg.buff, msg.type);
        sleep(1);
    }
    return 0;
}

3.5.3 消息队列删除端

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

int main(){
    //1.创建key
    key_t key = ftok(".",'q');
    if(-1 == key) printf("ftok error:%m\n"),exit(-1);
    printf("ftok success!\n");
    //2. 创建消息队列
    int msgid = msgget(key,IPC_CREAT | 0666);
    if(-1 == msgid) printf("msgget error:%m\n"),exit(-1);
    printf("msgget success!\n");
    //3. 删除当前消息队列
    msgctl(msgid,IPC_RMID,NULL);


    return 0;
}

3.5.6 运行结果

当发送端的消息类型是type = 2 时, 接收端将消息队列中 type为2的消息取出来处理, type为3的消息仍然在消息队列中

使用命令查看创建的消息队列 (已用字节数是刚刚的type为3的消息)

继续发送一个type为5的消息和一个type为6的消息,发现已用字节数变成了96

删除消息队列后

4. 旗语(信号量)

4.1 旗语(信号量定义)

sem(semaphore), 让多个进程不可能同时访问一块区域

4.2 sem(信号量 编程模型)

  1. 创建key ftok函数
  2. 创建旗语(信号量) semget函数
  3. 初始化旗语(信号量) semctl函数
  4. 使用旗语(信号量) semop函数
  5. 删除旗语(信号量) semctl函数

4.3 sem的一些函数原型

4.3.1 ftok函数

//头文件
#include <sys/types.h>
#include <sys/ipc.h>
//函数原型
key_t ftok(const char *pathname, int proj_id);

//返回值: 返回值为一个4byte的整数(返回-1失败)
//0--15  bit: pathname的st_ino属性的低16位
//16--23 bit: pathname的st_dev属性的低8位
//24--31 bit: pro_id的低8位

//参数一: 传入一个路径,一般使用当前路径"."
//参数二: 任意的一个整数,因为要做进程间通信,
//那么另一个进程需要与这个数保持一致才能找到对应的ipcid,一般只使用8个bit,因此取值范围在0--255

4.3.2 semget函数

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

int semget(key_t key, int nsems, int semflg);

//返回值: 返回一个整数(-1表示失败)
//参数一: ftok函数返回值
//参数二: 创建信号量的个数(一般创建一个)
//参数三: 主要是一些标志
// IPC_CREAT  不存在共享内存就创建,否则打开
// IPC_EXCL   不存在共享内存才创建,否则错误

4.3.3 semop函数

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

int semop(int semid, struct sembuf *sops, size_t nsops);

//返回值: 成功返回0, 失败返回-1
//参数一: semget函数返回值()
//参数二: 信号量的一些信息(用户可更改)
sops[0].sem_num = 0; 信号量的索引
sops[0].sem_op = 0;  加还是减以及加减的值
sops[0].sem_flg = 0; 一般设置为0
//参数三: 操作的次数

4.3.4 semctl函数

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

int semctl(int semid, int semnum, int cmd, ...);

//返回值: 失败返回-1
//参数一: semget函数返回值(信号量的标识id)
//参数二: 信号量的标识,标识使用第几个信号量(从0开始)
//参数三: 一个指向msqid_ds 的结构体指针
// IPC_STAT: 调用者必须对共享内存具有读权限
// IPC_SET: 对semid_ds 中的某些值做一些修改
// IPC_RMID: 表示销毁某个段
// IPC_INFO: 返回共享内存限制和参数的信息
// SEM_INFO: 返回一个seminfo的结构体
// SEM_STAT: 返回该内存段在内核数组的索引,该数组记录所有共享内存段的信息
// GETALL:   获取集合中所有的信号量
// GETNCNT:  返回集合中指定semnum的信号量
// GETPID:   返回指定semnum的sempid的值
// GETVAL:   返回指定semnum的semval的值
// GETZCNT:  返回集合中第一个信号量的semzcnt值
// SETALL:   为集合中所有信号量设置值
// SETVAL:   设置一个信号量的值
//参数四: 缺省参数, union semun类型的指针
 union semun {
               int              val;    /* SETVAL */
               struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
               unsigned short  *array;  /* Array for GETALL, SETALL */
               struct seminfo  *__buf;  /* Buffer for IPC_INFO*/
           };

4.4 旗语(信号量)的优势与缺点

4.4.1 优势

节省了打开文件以及关闭文件的时间,数据传输速率提高

4.4.2 缺点

一但被锁定, 在解锁之前出现程序崩溃等问题, 就会导致锁定的信号量无法恢复, 形成永久性的占用, 使用文件操作的方式则不会出现这种情况, 因为在进程退出的时候, 文件就会被关闭, 在该文件描述符上的锁定就会被自动解除。

4.5 旗语(信号量演示)

4.5.1 信号量加端

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

int main(){
    //1. 创建key
    key_t key = ftok(".",'s');
    if(-1 == key) printf("ftok error:%m\n"),exit(-1);
    printf("ftok success!\n");
    //2. 创建信号量
    int semid = semget(key,1,IPC_CREAT | 0654);
    if(-1 == semid) printf("semget error:%m\n"),exit(-1);
    printf("semget success!\n");

    //3. 使用旗语
    struct sembuf buf;
    buf.sem_num = 0;
    buf.sem_op = 1;     //加
    buf.sem_flg = 0;

    while(1){
        semop(semid,&buf,1); //操作一次
        sleep(1);
    }


    return 0;
}

4.5.2 信号量减端

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

union semun{
    int val;
    struct semid_ds* buf;
    unsigned short* array;
    struct seminfo* __buf;
};
int main(){
    //1. 创建key
    key_t key = ftok(".",'s');
    if(-1 == key) printf("ftok error:%m\n"),exit(-1);
    printf("ftok success!\n");
    //2. 创建信号量
    int semid = semget(key,1,IPC_CREAT | 0654);
    if(-1 == semid) printf("semget error:%m\n"),exit(-1);
    printf("semget success!\n");
    //3. 初始化信号量
    union semun u;
    u.val = 5;
    semctl(semid,0,SETVAL,u);
    //4. 使用旗语
    struct sembuf buf;
    buf.sem_num = 0;
    buf.sem_op = -1;    //减
    buf.sem_flg = 0;

    int n = 0;
    while(1){
        printf("卖出%d辆!\n",++n);
        semop(semid,&buf,1); //操作一次
    }

    return 0;
}

4.5.3 信号量删除

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

int main(){
    //1. 创建key
    key_t key = ftok(".",'s');
    if(-1 == key) printf("ftok error:%m\n"),exit(-1);
    printf("ftok success!\n");
    //2. 创建信号量
    int semid = semget(key,1,IPC_CREAT | 0654);
    if(-1 == semid) printf("semget error:%m\n"),exit(-1);
    printf("semget success!\n");

    //3. 删除旗语
    semctl(semid,0,IPC_RMID,NULL);

    return 0;
}

4.5.4 运行结果

设置信号量 0 初始值为5, 运行A后,再运行B:

ipcs -s 查看信号量信息:

删除创建的信号量后,ipcs -s 查看信号量信息:

5. 管理IPC的ipc命令簇

5.1 ipcs 查看命令

  1. -m 查看shm(共享内存)
  2. -q 查看msg(消息队列)
  3. -s 查看sem(信号量)

5.2 ipcrm 删除命令

  1. -m 删除shm(共享内存)
  2. -q 删除msg(消息队列)
  3. -s 删除sem(信号量)

注: shm msg sem 都必须先有一个key(key是根据fd来创建的)

相关文章
|
1月前
|
算法 Linux 调度
深入理解Linux操作系统的进程管理
本文旨在探讨Linux操作系统中的进程管理机制,包括进程的创建、执行、调度和终止等环节。通过对Linux内核中相关模块的分析,揭示其高效的进程管理策略,为开发者提供优化程序性能和资源利用率的参考。
70 1
|
4天前
|
消息中间件 Linux
Linux:进程间通信(共享内存详细讲解以及小项目使用和相关指令、消息队列、信号量)
通过上述讲解和代码示例,您可以理解和实现Linux系统中的进程间通信机制,包括共享内存、消息队列和信号量。这些机制在实际开发中非常重要,能够提高系统的并发处理能力和数据通信效率。希望本文能为您的学习和开发提供实用的指导和帮助。
47 20
|
24天前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
94 13
|
1月前
|
SQL 运维 监控
南大通用GBase 8a MPP Cluster Linux端SQL进程监控工具
南大通用GBase 8a MPP Cluster Linux端SQL进程监控工具
|
1月前
|
运维 监控 Linux
Linux操作系统的守护进程与服务管理深度剖析####
本文作为一篇技术性文章,旨在深入探讨Linux操作系统中守护进程与服务管理的机制、工具及实践策略。不同于传统的摘要概述,本文将以“守护进程的生命周期”为核心线索,串联起Linux服务管理的各个方面,从守护进程的定义与特性出发,逐步深入到Systemd的工作原理、服务单元文件编写、服务状态管理以及故障排查技巧,为读者呈现一幅Linux服务管理的全景图。 ####
|
2月前
|
缓存 算法 Linux
Linux内核的心脏:深入理解进程调度器
本文探讨了Linux操作系统中至关重要的组成部分——进程调度器。通过分析其工作原理、调度算法以及在不同场景下的表现,揭示它是如何高效管理CPU资源,确保系统响应性和公平性的。本文旨在为读者提供一个清晰的视图,了解在多任务环境下,Linux是如何智能地分配处理器时间给各个进程的。
|
2天前
|
C++ 芯片
【C++面向对象——类与对象】Computer类(头歌实践教学平台习题)【合集】
声明一个简单的Computer类,含有数据成员芯片(cpu)、内存(ram)、光驱(cdrom)等等,以及两个公有成员函数run、stop。只能在类的内部访问。这是一种数据隐藏的机制,用于保护类的数据不被外部随意修改。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。成员可以在派生类(继承该类的子类)中访问。成员,在类的外部不能直接访问。可以在类的外部直接访问。为了完成本关任务,你需要掌握。
33 18
|
2天前
|
存储 编译器 数据安全/隐私保护
【C++面向对象——类与对象】CPU类(头歌实践教学平台习题)【合集】
声明一个CPU类,包含等级(rank)、频率(frequency)、电压(voltage)等属性,以及两个公有成员函数run、stop。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。​ 相关知识 类的声明和使用。 类的声明和对象的声明。 构造函数和析构函数的执行。 一、类的声明和使用 1.类的声明基础 在C++中,类是创建对象的蓝图。类的声明定义了类的成员,包括数据成员(变量)和成员函数(方法)。一个简单的类声明示例如下: classMyClass{ public: int
30 13
|
2天前
|
编译器 数据安全/隐私保护 C++
【C++面向对象——继承与派生】派生类的应用(头歌实践教学平台习题)【合集】
本实验旨在学习类的继承关系、不同继承方式下的访问控制及利用虚基类解决二义性问题。主要内容包括: 1. **类的继承关系基础概念**:介绍继承的定义及声明派生类的语法。 2. **不同继承方式下对基类成员的访问控制**:详细说明`public`、`private`和`protected`继承方式对基类成员的访问权限影响。 3. **利用虚基类解决二义性问题**:解释多继承中可能出现的二义性及其解决方案——虚基类。 实验任务要求从`people`类派生出`student`、`teacher`、`graduate`和`TA`类,添加特定属性并测试这些类的功能。最终通过创建教师和助教实例,验证代码
20 5
|
2天前
|
存储 算法 搜索推荐
【C++面向对象——群体类和群体数据的组织】实现含排序功能的数组类(头歌实践教学平台习题)【合集】
1. **相关排序和查找算法的原理**:介绍直接插入排序、直接选择排序、冒泡排序和顺序查找的基本原理及其实现代码。 2. **C++ 类与成员函数的定义**:讲解如何定义`Array`类,包括类的声明和实现,以及成员函数的定义与调用。 3. **数组作为类的成员变量的处理**:探讨内存管理和正确访问数组元素的方法,确保在类中正确使用动态分配的数组。 4. **函数参数传递与返回值处理**:解释排序和查找函数的参数传递方式及返回值处理,确保函数功能正确实现。 通过掌握这些知识,可以顺利地将排序和查找算法封装到`Array`类中,并进行测试验证。编程要求是在右侧编辑器补充代码以实现三种排序算法
18 5