IO——进程间通讯 IPC

news2024/11/18 9:03:51

1. 进程间通信方式

(1) 早期进程间通信:
无名管道(pipe)、有名管道(fifo)、信号(signal)
(2) system V IPC:
共享内存(shared memory)、消息队列(message queue)、信号灯集(semaphore set)
(3) BSD:
套接字(socket)

2. 无名管道

2.1特点

(1) 只能用于具有亲缘关系的进程(父子)之间的通信
(2) 半双工的通信模式,具有固定的读端fd[0]和写端fd[1]。
(3) 管道可以看成是一种特殊的文件,对于它的读写可以使用文件IO如read、write函数。
(4) 管道是基于文件描述符的通信方式。当一个管道建立时,它会创建两个文件描述符 fd[0]和fd[1]。其中fd[0]固定用于读管道,而fd[1]固定用于写管道。

2.2函数接口

int pipe(int fd[2])//传int 数组首地址即可
    功能:创建无名管道
参数:文件描述符 fd[0]:读端  fd[1]:写端
返回值:成功 0
    失败 -1

2.3注意事项

(1) 当管道中无数据,读操作会阻塞
当管道中有数据关闭写端,可以将数据读出。
当管道中无数据关闭写端,读操作会立即返回。
(2) 管道中写满(管道大小64K)数据写操作会阻塞,一旦用4K空间(满后,至少读出4k大小数据后才能继续写),写继续
(3) 只有当管道读端存在时,向管道中写入数据才有意义。否则会导致管道破裂,向管道中写入数据进程会收到来自内核的SIGPIPE信号(通常时Broken pipe错误)

3. 有名管道

3.1特点

  1. 有名管道可以使互不相关的两个进程互相通信。
  2. 有名管道可以通过路径名来指出,并且在文件系统中可见,但内容存放在内存中。但是读写数据不会存在文件中,而是在管道中。(生成管道文件)
  3. 进程通过文件IO来操作有名管道
  4. 有名管道遵循先进先出规则(所以不能定位)
  5. 不支持如lseek() 操作

3.2函数接口

int mkfifo(const char *filename,mode_t mode);
功能:创建有名管道
参数:filename:有名管道文件名
       mode:权限
返回值:成功:0
       失败:-1,并设置errno号
注意对错误的处理方式:
如果错误是file exist时,注意加判断,如:if(errno == EEXIST)(头文件errno.h别忘了加)

注:函数只是在路径下创建管道文件,往管道中写的数据依然写在内核空间。
先创建有名管道,然后用文件IO操作:打开、读写和关闭。

3.3 注意事项

  1. 只写方式打开阻塞,一直到另一个进程把读打开
  2. 只读方式打开阻塞,一直到另一个进程把写打开(所以先读先写没关系,但要读写都打开才行)
  3. 可读可写,如果管道中没有数据,读阻塞

3.4 有名管道和无名管道的区别

在这里插入图片描述

4. 信号

kill -l:显示系统中的信号
kill -num PID:给指定进程发送信号

4.1概念

1)信号是在软件层次上对中断机制的一种模拟,是一种异步通信方式
2)信号可以直接进行用户空间进程和内核进程之间的交互,内核进程也可以利用它来通知用户空间进程发生了哪些系统事件。
3)如果该进程当前并未处于执行态,则该信号就由内核保存起来,直到该进程恢复执行再传递给它;如果一个信号被进程设置为阻塞,则该信号的传递被延迟,直到其阻塞被取消时才被传递给进程。

4.2信号的响应方式

1)忽略信号:对信号不做任何处理,但是有两个信号不能忽略:即SIGKILL及SIGSTOP。
2)捕捉信号:定义信号处理函数,当信号发生时,执行相应的处理函数。
3)执行缺省操作:Linux对每种信号都规定了默认操作

4.3信号种类

SIGINT(2):中断信号,Ctrl+C 产生,用于中断进程
SIGQUIT(3):退出信号, Ctrl+\ 产生,用于退出进程并生成核心转储文件(vscode 不能使用,在linux终端可以使用)
SIGKILL(9):终止信号,用于强制终止进程。此信号不能被捕获或忽略。
SIGALRM(14):闹钟信号,当由 alarm() 函数设置的定时器超时时产生。
SIGTERM(15):终止信号,用于请求终止进程。此信号可以被捕获或忽略。termination
SIGCHLD(17):子进程状态改变信号,当子进程停止或终止时产生。
SIGCONT(18):继续执行信号,用于恢复先前停止的进程。
SIGSTOP(19):停止执行信号,用于强制停止进程。此信号不能被捕获或忽略。
SIGTSTP(20):键盘停止信号,通常由用户按下 Ctrl+Z 产生,用于请求停止进程。

4.4 函数接口

4.4.1信号发送和挂起

#include <signal.h>
int kill(pid_t pid, int sig);
功能:给指定进程发送信号
参数:
    pid:指定进程
    sig:要发送的信号
返回值:
    成功:0
    失败:-1

int raise(int sig);
功能:向当前进程发送信号
参数:sig:信号
返回值:
    成功:0
    失败:-1
    相当于:kill(getpid(),sig);

int pause(void);
功能:用于将调用进程挂起,直到收到被捕获处理的信号为止。

4.4.2定时器

unsigned int alarm(unsigned int seconds)
功能:在进程中设置一个定时器。当定时器指定的时间到了时,它就向进程发送SIGALARM信号。系统对SIGALARM信号默认处理方式是退出进程(即收到闹钟信号退出进程)。
参数:seconds:定时时间,单位为秒
返回值:如果调用此alarm()前,进程中已经设置了闹钟时间,则返回上一个闹钟时间的剩余时间,否则返回0。
注意:一个进程只能有一个闹钟时间。如果在调用alarm时已设置过闹钟时间,则之前的闹钟时间被新值所代替。
常用操作:取消定时器alarm(0),返回旧闹钟余下秒数。

系统SIGALARM信号的响应默认是结束进程,如果不对闹钟信号进行捕捉那默认情况闹钟响了进程就直接结束了。

4.4.3 信号处理函数signal()

typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
功能:信号处理函数
参数:signum:要处理的信号
      handler:信号处理方式
          SIG_IGN:忽略信号  (忽略 ignore)
          SIG_DFL:执行默认操作 (默认 default)
          handler:捕捉信号 (handler为函数名,可以自定义)
                void handler(int sig){} //函数名可以自定义, 参数为要处理的信号
返回值:成功:设置之前的信号处理方式
        失败:-1

补充: typedef 给数据类型重命名的方式

#include <stdio.h>

//给普通数据类型int重命名
typedef int size4;        

//给指针类型int* 重命名
typedef int *int_p;       

//给数组类型int [10]重命名
typedef int intArr10[10]; 

//给函数指针void (*)()重命名
typedef void (*fun_p)(); 

void fun()
{
    printf("fun\n");
}

int main(int argc, char const *argv[])
{
    size4 a = 10;             //相当于int a
    int_p p = &a;             //相当于int* p
    intArr10 arr = {1, 2, 3}; //相当于int arr[10]
    fun_p fp = fun;           //相当于 void (* fp)();

    printf("%d\n", *p);
    printf("%d\n", arr[0]);
    fp();

    return 0;
}

5. 共享内存

1)共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝。
2)为了在多个进程间交换信息,内核专门留出了一块内存区,可以由需要访问的进程
将其映射到自己的私有地址空间。进程就可以直接读写这一内存区而不需要进行数据的拷贝,从而大大提高的效率。
3) 由于多个进程共享一段内存,因此也需要依靠某种同步机制,如互斥锁和信号量等

5.2步骤

(1) 创建key值: ftok()
(2) 创建或打开共享内存:shmget()
(3) 映射共享内存到用户空间:shmat()
(4) 撤销映射:shmdt()
(5) 删除共享内存:shmctl()

5.3函数接口

key_t ftok(const char *pathname, int proj_id);
功能:创建出来的具有唯一映射关系的一个key值,帮助操作系统用来标识一块共享内存
参数:
Pathname:已经存在的可访问文件的名字(存在的文件名即可,无关访问,但注意原文件的删除再创建会改变inode号,导致key值变化)
Proj_id:一个字符(因为只用低8位)
返回值:成功:key值
失败:-1
    // 将文件的索引节点号取出ls -i,前面加上proj_id得到key_t的返回值。如指定文件的索引节点号为65538,换算成16进制为 0x010002取后4位,而你指定的ID值为38,换算成16进制为0x26,则最后的key_t返回值为0x26010002。中间的01是系统编号。

int shmget(key_t key, size_t size, int shmflg);
功能:创建或打开共享内存
参数:
key  键值
size   共享内存的大小
shmflg   IPC_CREAT|IPC_EXCL|0777
    返回值:成功  shmid
出错    -1

    //当IPC_CREAT | IPC_EXCL时, 如果没有该块共享内存,则创建,并返回共享内存ID。若已有该块共享内存,则返回-1。

void  *shmat(int  shmid,const  void  *shmaddr,int  shmflg); //attaches
功能:映射共享内存,即把指定的共享内存映射到进程的地址空间用于访问
参数:
shmid   共享内存的id号
shmaddr   一般为NULL,表示由系统自动完成映射
如果不为NULL,那么有用户指定
shmflg:SHM_RDONLY就是对该共享内存只进行读操作
0     可读可写
返回值:成功:完成映射后的地址(后面的操作即可对开辟空间的地址进行操作)
出错:-1(地址)
用法:if((p = (char *)shmat(shmid,NULL,0)) == (char *)-1)

int shmdt(const void *shmaddr); //detaches
功能:取消映射
参数:要取消的地址
返回值:成功0  
失败的-1

int  shmctl(int  shmid,int  cmd,struct shmid_ds *buf); //control
功能:(删除共享内存),对共享内存进行各种操作
参数:
shmid   共享内存的id号
cmd     IPC_STAT 获得shmid属性信息,存放在第三参数
IPC_SET 设置shmid属性信息,要设置的属性放在第三参数
IPC_RMID:删除共享内存,此时第三个参数为NULL即可
buf    shmid所指向的共享内存的地址,空间被释放以后地址就赋值为null
返回:成功0 
失败-1
用法: shmctl(shmid,IPC_RMID,NULL);

5.4. 命令

ipcs -m: 查看系统中的共享内存
ipcrm -m shmid:删除共享内存

ps: 可能不能直接删除掉 还存在进程使用的共享内存。
这时候可以用ps -ef对进程进行查看,kill掉多余的进程后,再使用ipcs查看。

6. 信号灯集

线程: 全局变量, 同步通过信号量
初始化: sem_init(&sem,0,0);
申请资源:sem_wait(&sem); P操作 -1
释放资源:sem_post(&sem); V操作 +1

6.1 特点

信号灯(semaphore),也叫信号量,信号灯集是一个信号灯的集合。它是不同进程间或一个给定进程内部不同线程间同步的机制;
而Posix信号灯指的是单个计数信号灯:无名信号灯、有名信号灯。(咱们学的是无名信号灯)
System V的信号灯是一个或者多个信号灯的一个集合。其中的每一个都是单独的计数信号灯。
通过信号灯集实现共享内存的同步操作

6.2 步骤

(1) 创建key值: ftok
(2) 创建或打开信号灯集: semget
(3) 初始化信号灯: semctl
(4) PV操作: semop
(5) 删除信号灯集: semctl

6.3 命令

ipcs -s: 查看信号灯集
ipcrm -s semid: 删除指定的信号灯集
注意:有时候可能会创建失败,或者semid为0,所以用命令看看,删了重新创建就可以了。

6.4 函数接口

int semget(key_t key, int nsems, int semflg);
功能:创建/打开信号灯
参数:key:ftok产生的key值
    nsems:信号灯集中包含的信号灯数目
    semflg:信号灯集的访问权限,通常为IPC_CREAT|IPC_EXCL|0666
    返回值:成功:信号灯集ID
       失败:-1

int semctl ( int semid, int semnum,  int cmd…/*union semun arg*/);
功能:信号灯集合的控制(初始化/删除)
参数:semid:信号灯集ID
    semnum: 要操作的集合中的信号灯编号,信号灯编号从0开始
     cmd: 
        GETVAL:获取信号灯的值,返回值是获得值
        SETVAL:设置信号灯的值,需要用到第四个参数:共用体
        IPC_RMID:从系统中删除信号灯集合
返回值:成功 0
        失败 -1

        用法:
1. 初始化信号灯集:
需要 自定义 共用体
union semun{
    int val;
} mysemun;
mysemun.val=10;
semctl(semid,0,SETVAL,mysemun);  //把0号信号灯初始化

2. 获取信号灯初值: 函数semctl(semid,0,GETVAL); 的返回值就是信号灯的值

3. 删除信号灯集: semctl(semid,0,IPC_RMID);


int semop ( int semid, struct sembuf  *opsptr,  size_t  nops);
功能:对信号灯集合中的信号量进行PV操作
参数:semid:信号灯集ID
     opsptr:操作方式
     nops:  要操作的信号灯的个数 1个
返回值:成功 :0
      失败:-1
         struct sembuf {
             short  sem_num; // 要操作的信号灯的编号
             short  sem_op;  //    0 :  等待,直到信号灯的值变成0
             //   1  :  释放资源,V操作
             //   -1 :  申请资源,P操作                    
             short  sem_flg; // 0(阻塞),IPC_NOWAIT, SEM_UNDO
         };

用法:
申请资源P操作:
struct sembuf mysembuf;
mysembuf.sem_num = 0;
mysembuf.sem_op = -1;
mysembuf.sem_flg = 0;
semop(semid,&mysembuf,1);

释放资源V操作:
mysembuf.sem_num = 0;
mysembuf.sem_op = 1;
mysembuf.sem_flg = 0;
semop(semid,&mysembuf,1);

操作信号灯集:
注意:如果创建失败或者semid为0, 那就删除0重新执行创建就可以了(ipcs 查看semid,ipcrm -s semid 删除即可)

7. 消息队列

传统: 无名管道 有名管道 信号
system V: 共享内存 信号灯集 消息队列
按消息的类型添加或读取消息
队列原则

7.1 特点

消息队列是IPC对象(活动在内核级别的一种进程间通信的工具)的一种
一个消息队列由一个标识符 (即队列ID)来标识
消息队列就是一个消息的列表。用户可以在消息队列中添加消息、读取消息等
消息队列可以按照类型(自己设一个值作为类型)来发送/接收消息

7.2 步骤

(1) 创建key值: ftok
(2) 创建或打开消息队列 msgget()
(3) 添加消息:按照消息的类型把消息添加到已经打开的消息队列末尾 msgsnd()
(4) 读取消息: 可以按照消息类型把消息从队列中读走 msgrcv()
(5) 删除消息队列: msgctl()

7.3 操作命令

ipcs -q: 查看消息队列
ipcrm -q msgid: 删除消息队列
如果创建失败,也要先删除再创建

7.4 函数接口

int msgget(key_t key, int flag);
功能:创建或打开一个消息队列
参数:  key值
       flag:创建消息队列的权限IPC_CREAT|IPC_EXCL|0666
    返回值:成功:msgid
       失败:-1

int msgsnd(int msqid, const void *msgp, size_t size, int flag); 
功能:添加消息
参数:msqid:消息队列的ID
      msgp:指向消息的指针。常用消息结构msgbuf如下:
          struct msgbuf{
            long mtype;          //消息类型
            char mtext[N]}//消息正文
   size:发送的消息正文的字节数
   flag:IPC_NOWAIT消息没有发送完成函数也会立即返回    
         0:直到发送完成函数才返回
返回值:成功:0
      失败:-1
              使用:msgsnd(msgid, &msg,sizeof(msg)-sizeof(long), 0)
              注意:消息结构除了第一个成员必须为long类型外,其他成员可以根据应用的需求自行定义。

int msgrcv(int msgid,  void* msgp,  size_t  size,  long msgtype,  int  flag);
功能:读取消息
参数:msgid:消息队列的ID
     msgp:存放读取消息的空间
     size:接受的消息正文的字节数(sizeof(msgp)-sizeof(long))
    msgtype:
            0:接收消息队列中第一个消息。
            大于0:接收消息队列中第一个类型为msgtyp的消息.
    小于0:接收消息队列中类型值不小于msgtyp的绝对值且类型值又最小的消息。
     flag:
           0:若无消息函数会一直阻塞
           IPC_NOWAIT:若没有消息,进程会立即返回ENOMSG
返回值:成功:接收到的消息的长度
      失败:-1

    int msgctl ( int msgqid, int cmd, struct msqid_ds *buf );
功能:对消息队列的操作,删除消息队列
参数:msqid:消息队列的队列ID
     cmd:
        IPC_STAT:读取消息队列的属性,并将其保存在buf指向的缓冲区中。
        IPC_SET:设置消息队列的属性。这个值取自buf参数。
        IPC_RMID:从系统中删除消息队列。
     buf:消息队列缓冲区
返回值:成功:0
      失败:-1
    用法:msgctl(msgid, IPC_RMID, NULL

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1610434.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

局域网管理软件,适合在局域网内的管理软件有哪些?

信息技术的不断发展&#xff0c;局域网在企业、学校等机构中得到了广泛应用。 局域网不仅能够提高数据传输效率&#xff0c;还能实现资源共享和协同工作。 为了更好地管理和维护局域网&#xff0c;需要使用一些专业的局域网管理软件。 一、局域网的应用范围 局域网&#xff…

ruoyi element-ui 实现拖拉调整图片顺序

ruoyi element-ui 实现拖拉调整图片顺序 安装sortablejs https://sortablejs.com/npm 安装sortablejs npm install sortablejs --save相关options var sortable new Sortable(el, {group: "name", // or { name: "...", pull: [true, false, clone, …

华为 2024 届实习招聘——硬件-电源机试题(四套)

华为 2024 届实习招聘——硬件-电源机试题&#xff08;四套&#xff09; 部分题目分享&#xff0c;完整版带答案(有答案&#xff0c;答案非官方&#xff0c;未仔细校正&#xff0c;仅供参考&#xff09;&#xff08;共四套&#xff09; 获取&#xff08;WX:didadidadidida313&…

优思学院|ISO45001职业健康安全管理体系是什么?

ISO45001:2018是新公布的国际标准规范&#xff0c;全球备受期待的职业健康与安全国际标准&#xff08;OH&S&#xff09;于2018年公布&#xff0c;并将在全球范围内改变工作场所实践。ISO45001将取代OHSAS18001&#xff0c;成为全球工作场所健康与安全的参考。 ISO45001:201…

完整、免费的把pdf转word文档

在线工具网 https://www.orcc.online/pdf 支持pdf转word&#xff0c;免费、完整、快捷 登录网站 https://orcc.online/pdf 选择需要转换的pdf文件&#xff1a; 等待转换完成 点击蓝色文件即可下载 无限制&#xff0c;完整转换。

LLM推理加速,如何解决资源限制与效率挑战

©作者|Zane 来源|神州问学 LLM加速推理&#xff0c;GPU资源破局之道。 引言 大型语言模型&#xff08;LLM&#xff09;已经在多种领域得到应用&#xff0c;其重要性不言而喻。然而&#xff0c;随着这些模型变得越来越普遍&#xff0c;对GPU资源的需求也随之激增&#xff…

问卷回收率太低?用这几个小技巧轻松提升!

在进行调查研究时&#xff0c;高回收率是保障数据质量和调研成果有效性的关键因素之一。然而&#xff0c;有时候我们面对的情况是调查问卷的回收率较低&#xff0c;这可能会影响到数据的客观性和准确性。在这种情况下&#xff0c;我们需要采取措施来提高调查问卷的回收率&#…

MapReduce 机理

1.hadoop 平台进程 Namenode进程: 管理者文件系统的Namespace。它维护着文件系统树(filesystem tree)以及文件树中所有的文件和文件夹的元数据(metadata)。管理这些信息的文件有两个&#xff0c;分别是Namespace 镜像文件(Namespace image)和操作日志文件(edit log)&#xff…

Python --- 在python中安装NumPy,SciPy,Matplotlib以及scikit-learn(Windows平台)

在python中安装NumPy&#xff0c;SciPy&#xff0c;Matplotlib以及scikit-learn(Windows平台) 本文是针对(像我一样的)python新用户所写的&#xff0c;刚刚在电脑上装好python之后&#xff0c;所需的一些常见/常用的python第三方库/软件包的快速安装指引。包括了这些常用安装包…

0-1背包问题:贪心算法与动态规划的比较

0-1背包问题&#xff1a;贪心算法与动态规划的比较 1. 问题描述2. 贪心算法2.1 贪心策略2.2 伪代码 3. 动态规划3.1 动态规划策略3.2 伪代码 4. C语言实现5. 算法分析6. 结论7. 参考文献 1. 问题描述 0-1背包问题是组合优化中的一个经典问题。假设有一个小偷在抢劫时发现了n个…

C语言--函数递归

目录 1、什么是递归&#xff1f; 1.1 递归的思想 1.2 递归的限制条件 2. 递归举例 2.1 举例1&#xff1a;求n的阶乘 2.2 举例2&#xff1a;顺序打印⼀个整数的每⼀位 3. 递归与迭代 扩展学习&#xff1a; 早上好&#xff0c;下午好&#xff0c;晚上好 1、什么是递归&…

【Web】DASCTF X CBCTF 2022九月挑战赛 题解

目录 dino3d Text Reverser cbshop zzz_again dino3d 进来是一个js小游戏 先随便玩一下&#xff0c;显示要玩够1000000分 直接console改分数会被检测 先是JSFinder扫一下&#xff0c;扫出了check.php 到js里关键词索引搜索check.php 搜索sn&#xff0c;发现传入的参数是…

上古掌控安全的神-零:Spring Security5.x到Spring Security6.x的迁移

1. 本文概述 之前有写过一篇关于Spring Security的文章&#xff0c;但那已经是相对比较旧的版本了&#xff0c;就目前Spring Security6.0来说&#xff0c;这其中出现了不少的变动和更新&#xff0c;很多API的使用也是有不小的变化&#xff0c;所以我觉得有必要再写几篇文章学习…

OpenCV4.10使用形态运算提取水平线和垂直线

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;OpenCV的查找命中或未命中 下一篇&#xff1a;OpenCV4.9图像金字塔-CSDN博客 目标 在本教程中&#xff0c;您将学习如何&#xff1a; 应用两个非常常见的形态运算符&#xff08;即膨胀和…

java/C#语言开发的医疗信息系统10套源码

java/C#语言开发的医疗信息系统10套源码 云HIS系统源码&#xff0c;云LIS系统源码&#xff0c;PEIS体检系统&#xff0c;手麻系统 源 码&#xff0c;PACS系统源码&#xff0c;微源预约挂号源码&#xff0c;医院绩效考核源码&#xff0c;3D智能导诊系统源码&#xff0c;ADR药物…

数据分析场景,连号相关业务

连号相关业务 业务场景&#xff1a;现在需要从a列一堆编号中&#xff0c;将连号范围在10以内的数据分别分成一组。 先看实先效果 演示的为db2数据库&#xff0c;需要含有窗口函数&#xff0c;或者可以获取到当前数据偏移的上一位数据 第一步&#xff1a;将A列数据正序第二步…

【笔试强训_Day06】

文章目录 1.字符串相乘 1.字符串相乘 题目链接 解题思路&#xff1a; 高精度乘法&#xff0c;注意要学会下面这种列式相乘的形式&#x1f34e; 注意细节❗&#xff1a; ① &#x1f34e; 首先把列式相乘的数据都存放到数组中去&#xff0c; 然后再对数组中的数据进行取余进…

Web开发:ASP.NET CORE的前端demo(纯前端)

目录 一、建立项目 二、删除无用文件 三、样式添加 四、写一个登录页面 五、登录主界面 一、建立项目 二、删除无用文件 三、样式添加 将你的图片资源添加在wwwroot下方&#xff0c;例如pics/logo.png 四、写一个登录页面 将Privacy.cshtml改为 Forget.cshtml &#xff0…

喜报 | 英码科技顺利通过2023年度广东省工程技术研究中心认定

近日&#xff0c;广东省科学技术厅公示了2023年度广东省工程技术研究中心的名单&#xff0c;英码科技设立的“广东省人工智能与边缘计算工程技术研究中心”顺利通过2023年度广东省工程技术研究中心的认定&#xff1b;英码科技在边缘计算领域的技术创新能力、科技成果转化再次获…

452. 用最少数量的箭引爆气球[排序+贪心]

https://leetcode.cn/problems/minimum-number-of-arrows-to-burst-balloons/description/?envTypestudy-plan-v2&envIdtop-interview-150 题目描述 有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points &#xff0c;其中points[i] [xst…