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来创建的)

相关文章
|
8月前
|
并行计算 Linux
Linux内核中的线程和进程实现详解
了解进程和线程如何工作,可以帮助我们更好地编写程序,充分利用多核CPU,实现并行计算,提高系统的响应速度和计算效能。记住,适当平衡进程和线程的使用,既要拥有独立空间的'兄弟',也需要在'家庭'中分享和并行的成员。对于这个世界,现在,你应该有一个全新的认识。
304 67
|
7月前
|
Web App开发 Linux 程序员
获取和理解Linux进程以及其PID的基础知识。
总的来说,理解Linux进程及其PID需要我们明白,进程就如同汽车,负责执行任务,而PID则是独特的车牌号,为我们提供了管理的便利。知道这个,我们就可以更好地理解和操作Linux系统,甚至通过对进程的有效管理,让系统运行得更加顺畅。
223 16
|
7月前
|
Unix Linux
对于Linux的进程概念以及进程状态的理解和解析
现在,我们已经了解了Linux进程的基础知识和进程状态的理解了。这就像我们理解了城市中行人的行走和行为模式!希望这个形象的例子能帮助我们更好地理解这个重要的概念,并在实际应用中发挥作用。
143 20
|
6月前
|
监控 Shell Linux
Linux进程控制(详细讲解)
进程等待是系统通过调用特定的接口(如waitwaitpid)来实现的。来进行对子进程状态检测与回收的功能。
131 0
|
6月前
|
存储 负载均衡 算法
Linux2.6内核进程调度队列
本篇文章是Linux进程系列中的最后一篇文章,本来是想放在上一篇文章的结尾的,但是想了想还是单独写一篇文章吧,虽然说这部分内容是比较难的,所有一般来说是简单的提及带过的,但是为了让大家对进程有更深的理解与认识,还是看了一些别人的文章,然后学习了学习,然后对此做了总结,尽可能详细的介绍明白。最后推荐一篇文章Linux的进程优先级 NI 和 PR - 简书。
201 0
|
6月前
|
存储 Linux Shell
Linux进程概念-详细版(二)
在Linux进程概念-详细版(一)中我们解释了什么是进程,以及进程的各种状态,已经对进程有了一定的认识,那么这篇文章将会继续补全上篇文章剩余没有说到的,进程优先级,环境变量,程序地址空间,进程地址空间,以及调度队列。
133 0
|
6月前
|
Linux 调度 C语言
Linux进程概念-详细版(一)
子进程与父进程代码共享,其子进程直接用父进程的代码,其自己本身无代码,所以子进程无法改动代码,平时所说的修改是修改的数据。为什么要创建子进程:为了让其父子进程执行不同的代码块。子进程的数据相对于父进程是会进行写时拷贝(COW)。
184 0
|
消息中间件 存储 Linux
Linux IPC小结
IPC进程间通信(Inter-Process Communication)就是指多个进程之间相互通信,交换信息的方法。Linux IPC基本上都是从Unix平台上继承而来的。
1000 0
|
3月前
|
Linux 应用服务中间件 Shell
二、Linux文本处理与文件操作核心命令
熟悉了Linux的基本“行走”后,就该拿起真正的“工具”干活了。用grep这个“放大镜”在文件里搜索内容,用find这个“探测器”在系统中寻找文件,再用tar把东西打包带走。最关键的是要学会使用管道符|,它像一条流水线,能把这些命令串联起来,让简单工具组合出强大的功能,比如 ps -ef | grep 'nginx' 就能快速找出nginx进程。
二、Linux文本处理与文件操作核心命令
|
3月前
|
Linux
linux命令—stat
`stat` 是 Linux 系统中用于查看文件或文件系统详细状态信息的命令。相比 `ls -l`,它提供更全面的信息,包括文件大小、权限、所有者、时间戳(最后访问、修改、状态变更时间)、inode 号、设备信息等。其常用选项包括 `-f` 查看文件系统状态、`-t` 以简洁格式输出、`-L` 跟踪符号链接,以及 `-c` 或 `--format` 自定义输出格式。通过这些选项,用户可以灵活获取所需信息,适用于系统调试、权限检查、磁盘管理等场景。
318 137