Linux 秋招必知必会(四、信号、高级 I/O)

八、信号

57. 信号的基本特征

  • 定义:信号是事件发生时对进程的通知机制,也可以把它称为软件中断
  • 信号处理方式
    • 忽略信号
      • 大多数信号都可以使用这种方式进行处理,但 SIGKILL 和 SIGSTOP 绝对不能被忽略
      • 如果忽略某些由硬件异常产生的信号,则进程的运行行为是未定义的
    • 捕获信号
      • 当信号到达进程后,执行预先绑定好的信号处理函数
      • Linux 系统提供系统调用 signal() 用于注册信号处理函数
    • 执行系统默认操作
      • 进程不对该信号事件作出处理,而是交由系统进行处理,每一种信号都会有其对应的系统默认的处理方式
      • 对大多数信号来说,系统默认的处理方式就是终止该进程
  • 信号是异步的
    • 产生信号的事件对进程而言是随机出现的,进程无法预测该事件产生的准确时间,进程不能通过简单地测试一个变量或使用系统调用来判断是否产生了一个信号,这就如同硬件中断事件,程序是无法得知中断事件产生的具体时间,只有当产生中断事件时才会告知程序,然后打断当前程序的正常执行流程、跳转去执行中断服务函数,这就是异步处理方式
  • 信号本质上是 int 类型数字编号
    • 这就好比硬件中断所对应的中断号。内核针对每个信号,都给其定义了一个唯一的整数编号,从数字 1 开始顺序展开。并且每一个信号都有其对应的名字(其实就是一个宏),信号名字与信号编号是一一对应关系,但是由于每个信号的实际编号随着系统的不同可能会不一样)
    • 不存在编号为 0 的信号,信号编号是从 1 开始的

58. 信号产生方式

  • 按键产生
    • Ctrl + c → (2)SIGINT(终止/中断) “INT” ---- Interrupt
    • Ctrl + z → (20)SIGTSTP(暂停/停止) “T” ---- Terminal 终端
    • Ctrl + \ → (3)SIGQUIT(退出)
  • 系统调用产生
    • 如:kill、raise、abort
  • 软件条件产生
    • 如:定时器 alarm
    • 使用 alarm() 函数可以设置一个定时器(闹钟),当定时器时间到,内核会向进程发送 SIGALRM 信号
  • 硬件异常产生
    • 除 0 操作 → (8)SIGFPE (浮点数例外) “F” -----float 浮点数
    • 非法访问内存 → (11)SIGSEGV (段错误)
    • 总线错误 → (7)SIGBUS
  • 命令产生
    • kill 命令:kill() 系统调用可将信号发送给指定的进程或进程组中的每一个进程

59. 信号的分类

59.1 可靠信号与不可靠信号
  • Linux 信号机制基本上是从 UNIX 系统中继承过来的,早期 UNIX 系统中的信号机制存在问题:进程每次处理信号后,就将对信号的响应设置为系统默认操作
  • 早期 UNIX 下的不可靠信号主要是指
    • 进程可能对信号做出错误的反应
    • 信号可能丢失(处理信号时又来了新的信号,则导致信号丢失)
  • Linux 支持不可靠信号,但是对不可靠信号机制做了改进
    • 在调用完信号处理函数后,不必重新调用 signal(),Linux 下的不可靠信号问题主要指的是信号可能丢失
    • Linux 系统下,信号值小于 SIGRTMIN(34)的信号都是不可靠信号
  • 新增加了一些信号 (SIGRTMIN(34)~ SIGRTMAX(64)),并把它们定义为可靠信号
    • 编号 1~31 所对应的是不可靠信号,编号 34~64 对应的是可靠信号
    • 可靠信号支持排队,不会丢失,可靠信号并没有一个具体对应的名字
    $ kill -l
     1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
     6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
    11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
    16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
    21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
    26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
    31) SIGSYS	34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
    38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
    43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
    48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
    53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
    58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
    63) SIGRTMAX-1	64) SIGRTMAX
    
59.2 实时信号与非实时信号
  • 实时信号与非实时信号其实是从时间关系上进行的分类,与可靠信号与不可靠信号相对应
    • 非实时信号都不支持排队,都是不可靠信号
    • 实时信号都支持排队,都是可靠信号
    • 实时信号保证了发送的多个信号都能被接收,实时信号是 POSIX 标准的一部分,可用于应用进程
    • 一般也把非实时信号(不可靠信号)称为标准信号

60. 常见信号与默认行为

  • term 表示终止进程
  • core 表示生成核心转储文件,核心转储文件可用于调试
  • ignore 表示忽略信号
  • cont 表示继续运行进程
  • stop 表示停止进程(停止不等于终止,而是暂停
    在这里插入图片描述

61. signal() 和 sigaction()

  • 系统调用 signal() 函数可将信号的处理方式设置为捕获信号、忽略信号以及系统默认操作
    #include <signal.h>
    
    typedef void (*sig_t)(int);
    sig_t signal(int signum, sig_t handler);
    
  • sigaction() 系统调用是设置信号处理方式的另一选择,推荐使用 sigaction() 函数。虽然 signal() 函数简单好用,而 sigaction() 更复杂,但 sigaction() 更具灵活性以及移植性
    • sigaction() 允许单独获取信号的处理函数而不是设置
    • 还可以设置各种属性对调用信号处理函数时的行为施以更加精准的控制

62. 信号集

  • 信号集(signalset)用于表示多个信号(一组信号)的数据类型,信号集其实就是 sigset_t 类型数据结构
  • Linux 内核的进程控制块 PCB 是一个结构体 task_struct,除了包含进程 id、状态、工作目录、用户 id、组 id 和文件描述符表,还包含了信号相关的信息,主要指:阻塞信号集和未决信号集
    • 阻塞信号集 (信号屏蔽字、信号掩码)
      • 本质是位图,用来记录信号的屏蔽状态。将某些信号加入集合,对他们设置屏蔽,当屏蔽某信号后,当再收到该信号时,该信号的处理将推后 (一直处于未决状态,直到解除屏蔽)
    • 未决信号集
      • 本质是位图,用来记录信号的处理状态。信号产生,未决信号集中描述该信号的位立刻翻转为 1,表示信号处于未决状态;当信号被处理则对应位翻转回 0,这一时刻往往非常短暂
      • 信号产生后由于某些原因 (主要是阻塞) 不能抵达。这类信号的集合称之为未决信号集。在阻塞解除前,信号一直处于未决状态

63. sigsuspend() 和 sigpending()

  • 阻塞等待信号:更改进程的信号掩码可以阻塞所选择的信号,或解除对它们的阻塞,可以保护不希望由信号中断的关键代码段。如果希望对一个信号解除阻塞后,然后调用 pause() 以等待之前被阻塞的信号的传递,如何实现?
    • 使用 sigsuspend() 系统调用将恢复信号掩码和 pause() 挂起进程这两个动作封装成一个原子操作
    • sigsuspend() 会将进程的信号掩码设置为参数 mask 所指向的信号集,然后挂起进程,直到捕获到信号被唤醒(如果捕获的信号是 mask 信号集中的成员,将不会唤醒、继续挂起),并从信号处理函数返回,一旦从信号处理函数返回,sigsuspend() 会将进程的信号掩码恢复成调用前的值
  • 实时信号:如果进程当前正在执行信号处理函数,在处理信号期间接收到了新的信号,如果该信号是信号掩码中的成员,那么内核会将其阻塞,将该信号添加到进程的等待信号集(等待被处理的信号)中,为确定进程中处于等待状态的是哪些信号,可以使用 sigpending() 函数获取

九、高级 I/O

64. 非阻塞 I/O

  • 阻塞就是进入了休眠状态,交出了 CPU 控制权
  • 阻塞 I/O 就是对文件的 I/O 操作(读写操作)是阻塞式的,非阻塞 I/O 就是对文件的 I/O 操作是非阻塞的
    • 阻塞式 I/O:对于某些文件类型(读管道文件、网络设备文件和字符设备文件),当对文件进行读操作时,如果数据未准备好或文件当前无数据可读,那么读操作可能会使调用者阻塞,直到有数据可读时才会被唤醒
    • 非阻塞式 I/O:即使没有数据可读也不会被阻塞,而是会立马返回错误
  • 普通文件不管读写多少个字节数据,read() 或 write() 一定会在有限的时间内返回,所以普通文件总是以非阻塞的方式进行 I/O 操作,但管道文件、设备文件等,既可使用阻塞式 I/O 操作,也可使用非阻塞式 I/O 进行操作

65. 阻塞 I/O 的优缺点

  • 当对文件进行读取操作时,如果文件当前无数据可读
    • 阻塞式 I/O 会将调用者应用程序挂起、进入休眠阻塞状态,直到有数据可读时才会解除阻塞,阻塞式 I/O 的困境:无法实现并发读取(同时读取),主要原因在于阻塞
    • 而对于非阻塞 I/O,应用程序不会被挂起,而是会立即返回,它要么一直轮训等待,直到数据可读,要么直接放弃
  • 优点
    • 能提升 CPU 的处理效率,当自身条件不满足时,进入阻塞状态并交出 CPU 资源,将 CPU 资源让给别人使用
    • 而非阻塞式则是抓紧利用 CPU 资源(如不断地去轮训),这样就会导致该程序占用非常高的 CPU 使用率

66. I/O 多路复用

虽然使用非阻塞式 I/O 解决了阻塞式 I/O 情况下并发读取文件所出现的问题,但使得程序的 CPU 占用率特别高,为了解决这个问题,就要用到 I/O 多路复用方法

  • I/O 多路复用通过一种机制,可以监视多个文件描述符,一旦某个文件描述符(也就是某个文件)可以执行 I/O 操作时,能够通知应用程序进行相应的读写操作
    • I/O 多路复用技术是为了解决:在并发式 I/O 场景中使进程或线程不阻塞于某个特定的 I/O 系统调用
    • I/O 多路复用一般用于并发非阻塞 I/O(多路非阻塞 I/O),如:既要读取鼠标、又要读取键盘
    • I/O 多路复用特征:外部阻塞式,内部监视多路 I/O

67. select() 和 poll()

采用两个功能几乎相同的系统调用来执行 I/O 多路复用操作,分别是 select() 和 poll()

  • 调用 select() 函数将阻塞直到有以下事情发生

    • 1、readfds、writefds 或 exceptfds 指定的文件描述符中至少有一个成为就绪态
      • readfds 是用来检测读是否就绪(是否可读)的文件描述符集合
      • writefds 是用来检测写是否就绪(是否可写)的文件描述符集合
      • exceptfds 是用来检测异常情况是否发生的文件描述符集合
      • 如果这三个参数都设置为 NULL,则可以将 select() 当做为一个类似于 sleep() 休眠的函数来使用,通过 select() 函数的最后一个参数 timeout 来设置休眠时间
    • 2、该调用被信号处理函数中断
    • 3、参数 timeout 中指定的时间上限已经超时
  • 在 poll() 函数中,需要构造一个 struct pollfd 类型的数组,每个数组元素指定一个文件描述符以及对该文件描述符所关心的条件(数据可读、可写或异常情况)

    #include <poll.h>
    
    int poll(struct pollfd *fds, nfds_t nfds, int timeout);
    
    // 调用者初始化 events 来指定需要为文件描述符 fd 做检查的事件
    // 当 poll() 函数返回时,revents 变量由 poll() 函数内部进行设置,用于说明文件描述符 fd 发生了哪些事件
    struct pollfd {
        int fd;         /* 文件描述符 */
        short events;   /* 位掩码:requested events */
        short revents;  /* 位掩码:returned events */
    };
    
  • 使用 select() 或 poll() 时需要注意一个问题

    • 当监测到某一个或多个文件描述符成为就绪态(可读或写)时,需要执行相应的 I/O 操作以清除该状态,否则该状态会一直存在,那么下一次调用 select() 或 poll() 时,文件描述符已经处于就绪态了,将直接返回

68. 异步 I/O

  • 在 I/O 多路复用中,进程通过系统调用 select() 或 poll() 来主动查询文件描述符上是否可以执行 I/O 操作
  • 而异步 I/O 中,当文件描述符上可执行 I/O 操作时,进程可以请求内核为自己发送一个信号,之后进程就可执行任何其它的任务直到文件描述符可执行 I/O 操作为止,此时内核会发送信号给进程,异步 I/O 通常也称信号驱动 I/O
  • 异步 I/O 执行步骤
    • 通过指定 O_NONBLOCK 标志使能非阻塞 I/O
    • 通过指定 O_ASYNC 标志使能异步 I/O
    • 设置异步 I/O 事件的接收进程
      • 也就是当文件描述符上可执行 I/O 操作时会发送信号通知该进程,通常将调用进程设置为异步 I/O 事件的接收进程
    • 为内核发送的通知信号注册一个信号处理函数
      • 默认情况下,异步 I/O 的通知信号是 SIGIO

69. 存储映射 I/O

  • 存储映射 I/O 是一种基于内存区域的高级 I/O 操作,它能将一个文件映射到进程地址空间中的一块内存区域中

    • 当从这段内存中读数据时,就相当于读文件中的数据(read 操作)
    • 将数据写入这段内存时,则相当于将数据直接写入文件中(write 操作)
    • 这样就可以在不使用基本 I/O 操作函数 read() 和 write() 的情况下执行 I/O 操作
  • 普通 I/O 与存储映射 I/O 比较

    • 普通 I/O 方式的缺点
      • 普通 I/O 方式一般是通过调用 read() 和 write() 函数实现对文件读写,使用 read() 和 write() 读写文件时,函数经过层层调用才能最终操作文件,效率会比较低,使用标准 I/O(库函数 fread()、fwrite())同样如此(标准 I/O 就是对普通 I/O 的一种封装)
      • 只有当数据量比较大时,效率的影响才会比较明显,如果数据量比较小则影响并不大,使用普通的 I/O 方式还是非常方便的
    • 存储映射 I/O 的优点
      • 存储映射 I/O 的实质其实是共享
      • 使用存储映射 I/O 减少了数据的复制操作,效率比普通 I/O 高
    • 存储映射 I/O 的不足
      • 所映射的文件只能是固定大小,因为文件所映射的区域已经在调用 mmap() 函数时通过 length 参数指定
      • 文件映射的内存区域的大小必须是系统页大小的整数倍
      • 使用存储映射 I/O 在进行大数据量操作时比较有效,对于少量数据则使用普通 I/O 方式更方便

70. 文件锁

多个进程同时操作同一文件,很容易导致文件中的数据发生混乱,因为多个进程对文件进行 I/O 操作时,容易产生竞争状态,导致文件中的内容与预想的不一致

  • 进程有时需要确保只有它自己能够对某一文件进行 I/O 操作,在这段时间内不允许其它进程对该文件进行 I/O 操作

    • Linux 系统提供了文件锁机制来实现:文件锁是用于对共享资源的访问进行保护的机制,对文件上锁,来避免多个进程同时操作同一文件时产生竞争状态
  • 文件锁分类

    • 建议性锁
      • 本质上是一种协议,程序访问文件前先对文件上锁,上锁成功后再访问文件
        在文件没有上锁的情况下直接访问文件也可以实现,但这样的话建议性锁就没有起作用
    • 强制性锁
      • 如果进程对文件上了强制性锁,其它进程在没有获取到文件锁的情况下是无法对文件进行访问的
      • 原因:强制性锁会让内核检查每一个 I/O 操作(如 read()、write()),验证调用进程是否是该文件锁的拥有者,如果不是将无法访问文件
      • 采取强制性锁对性能的影响很大,每次进行读写操作都必须检查文件锁
  • flock() 加锁

    • 使用 flock() 函数可以对文件加锁或者解锁,但只能产生建议性锁
    • 对于 flock(),同一个文件不会同时具有共享锁和互斥锁
  • fcntl() 加锁

    • flock() 仅支持对整个文件进行加锁/ 解锁,而 fcntl() 可以对文件的某个区域(某部分内容)进行加锁/解锁 ,可以精确到某一个字节数据
    • flock() 仅支持建议性锁类型,而 fcntl() 可支持建议性锁和强制性锁两种类型,但一般不建议使用强制性锁
  • lockf() 函数加锁

    • lockf() 函数是一个库函数,其内部基于 fcntl() 实现,所以 lockf() 是对 fcntl 锁的一种封装

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

lv_micropython to download and building

想要在ESP32-C3使用Micropython开发GUI&#xff0c;所以需要编译lv_micropython&#xff0c;当前github上的版本是9.1.0。 一、开发环境 因为编译lv_micropython需要在linux系统下&#xff0c;但是我的电脑是windows系统&#xff0c;所以我在windows系统上安装了VMware虚拟机&…

【matlab非线性规划工具箱安装1 SeDuMi 1.3工具箱】

【matlab非线性规划工具箱安装1 SeDuMi 1.3工具箱】 该博客是非线性手眼标定代码中所依赖的matlab工具箱的安装内容&#xff0c;除了进行手眼标定以外&#xff0c;该工具箱还可以用于其他的非线性规划问题 手眼标定传送门&#xff1a; 【从零开始进行高精度手眼标定 eye in …

Steam平台游戏发行流程

Steam平台游戏发行流程 大家好我是艾西&#xff0c;一个做服务器租用的网络架构师也是游戏热爱者&#xff0c;经常在steam平台玩各种游戏享受快乐生活。去年幻兽帕鲁以及雾锁王国在年底横空出世&#xff0c;幻兽帕鲁更是在短短一星期取得了非常好的成绩&#xff0c;那么作为游戏…

计算机网络——CSMA/CD协议以及相关习题

目录 前言 引言 CSMA/CD协议 CSMA与CSMA/CD的区别 CSMA/CD流程 前言 本博客是博主用于复习计算机网络的博客&#xff0c;如果疏忽出现错误&#xff0c;还望各位指正。 引言 最早的以太网&#xff0c;许多计算机都连接在一根总线上工作——广播通信方式。 总线的特点想…

JavaScript教程(十二)--- 使用‘类’

使用类 JavaScript 是一个基于原型的语言——一个对象的行为取决于它自身的属性及其原型的属性。对类来说&#xff0c;相较于与其他面向对象的语言&#xff0c;譬如 Java&#xff0c;创建对象的多层级结构及其属性的继承关系需要更多的代码行。本节&#xff0c;我们将展示如何…

windows搭建ftp服务器

安装iis 点击安装即可,搜索iis打开 创建ftp服务器 身份验证&#xff1a;只勾选匿名&#xff0c;不勾选基本&#xff0c;网上的很多教程会添加基本&#xff0c;导致的问题会出现浏览提需要输入账号密码的情况&#xff0c;这里为了方便大家更直观的感受FTP建立的过程&#xff0…

新手做抖店这个操作赶快停止!不听“废店”只是早晚的事!

哈喽~我是电商月月 互联网的发展&#xff0c;做什么事情都是公开透明的&#xff0c;做抖音小店也是 大家都会在网上搜索教程&#xff0c;技巧&#xff0c;但最终还是有好多人都失败了 那是因为这些流程技巧不正确吗&#xff1f;其实并不是&#xff0c;很多小技巧都是有用的&…

CTF-遗留的压缩包

题目描述&#xff1a;小蓝同学给你发来了他自己开发的网站链接&#xff0c;他说他故意留下了一个压缩包文件&#xff0c;里面有网站的源代码&#xff0c;他想考验一下你的网络安全技能。 下发容器&#xff0c;访问链接&#xff0c;发现都是无关内容 联想到标题说有遗留的压缩…

数模 线性规划模型理论与实践

线性规划模型理论与实践 1.1 线性规划问题 在人们的生产实践中&#xff0c;经常会遇到如何利用现有资源来安排生产&#xff0c;以取得最大经济效益的问题。此类问题构成了运筹学的一个重要分支一数学规划&#xff0c;而线性规划(Linear Programming 简记LP)则是数学规划的一个…

openjudge_2.5基本算法之搜索_166:The Castle

题目 166:The Castle 总时间限制: 1000ms 内存限制: 65536kB 描述 Figure 1 shows the map of a castle.Write a program that calculates how many rooms the castle hashow big the largest room is The castle is divided into m * n (m<50, n<50) square modules.…

Linux 内核学习(1) --- 时钟子系统

标题 时钟系统说明时钟树Clock Provider时钟通用数据结构clock_device 的注册clock_provider DTS配置和注册clock consumer时钟系统总结 时钟系统说明 时钟就是 SoC 中的脉搏&#xff0c;由它来控制各个部件按各自的节奏跳动。比如&#xff0c;CPU主频设置&#xff0c;串口的波…

切面条(蓝桥杯)

目录 题目 分析 代码实现 题目 一根高筋拉面&#xff0c;中间切一刀&#xff0c;可以得到2根面条。 如果先对折1次&#xff0c;中间切一刀&#xff0c;可以得到3根面条。 如果连续对折2次&#xff0c;中间切一刀&#xff0c;可以得到5根面条。 那么&#xff0c;连续对折1…

【报名指南】2023-2024学年AILD劳动技能大赛初赛报名流程

温馨提示&#xff1a; 1.AILD劳动技能大赛免费报名参赛。报名网址&#xff1a;aild.org.cn 2.报名时间即日起至5月31日。&#xff08;上海赛区线下挑战项目4月25日报名截止&#xff0c;线上挑战项目5月31日报名截止&#xff09;。 3.指导教师只能为行政备案学校的在职教师。…

C语言 数据输入输出

本文 我们来说 数据的输入与输出 及数据的运算 在程序的运算工程中 往往需要输入一些数据 而程序的运算 所得到的运算结果又需要输出给用户 因此 数据的输入与输出 就显得非常重要 在C语言中 不提供专门的输入输出语句 所有的输入输出 都是通过对标准库的调用 来实现的 一般 …

itop4412内核编译_编译自定义函数到内核

我的itop4412开发板是半路捡的&#xff0c;所以没办法加他们的售后群&#xff0c;遇到的问题只好一点点记录吧 内核驱动编译 在日常工作过程中&#xff0c;编写内核程序可能机会不多&#xff0c;但是将厂商提供的内核源码编译到固件中&#xff0c;这个技能还是必须掌握的。 i…

认识异常(1)

❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; hellohello~&#xff0c;大家好&#x1f495;&#x1f495;&#xff0c;这里是E绵绵呀✋✋ &#xff0c;如果觉得这篇文章还不错的话还请点赞❤️❤️收藏&#x1f49e; &#x1f49e; 关注&#x1f4a5;&a…

系统架构最佳实践 -- 一般优惠券平台系统架构设计

优惠券是商城的一种基础的营销工具&#xff0c;在目前c端用户对于电子优惠券已经非常熟悉的情况下&#xff0c;一般自营商城的营销活动系统&#xff0c;都是从优惠券开始搭建。 一、名词定义 基于个人理解&#xff0c;为方便表述&#xff0c;首先对可能产生歧义的名词进行如下…

十九.案例演示---天猫订单分析

目录 1.数据预处理 2.对订单状况进行分析 3.不同省份订单数详情 4.省份地图绘制 5.不同星期&#xff0c;订单分布 6.订单金额与订单数量 本次案例演示数据条数为:28010 import pandas as pd from pyecharts import options as optsdf_data pd.read_excel(../data/天猫订单…

【笔记】探索生成范式:大型语言模型在信息提取中的作用

探索生成范式&#xff1a;大型语言模型在信息提取中的作用 摘要介绍 &#x1f308;你好呀&#xff01;我是 是Yu欸 &#x1f30c; 2024每日百字篆刻时光&#xff0c;感谢你的陪伴与支持 ~ &#x1f680; 欢迎一起踏上探险之旅&#xff0c;挖掘无限可能&#xff0c;共同成长&am…

五、书架开发--3.弹出框功能开发、离线缓存功能开发

实现弹出框真实业务逻辑 私密阅读tab业务逻辑 1、根据点击的tab不同&#xff0c;从而展示出不同的popup弹窗 每个tab中都有自己的index&#xff0c;点击的时候获取这个index&#xff0c;就可以知道当前点击的是哪个tab&#xff0c;然后用switch-case来根据不同的index展示不…