




已阅读5页,还剩65页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第四章进程间通信 管道和信号 1 2 进程间通信 PIPE 进程间通信 FIFO 3 信号中断处理 进程通信有如下一些目的 A 数据传输 一个进程需要将它的数据发送给另一个进程 发送的数据量在一个字节到几M字节之间 B 共享数据 多个进程想要操作共享数据 一个进程对共享数据的修改 别的进程应该立刻看到 C 通知事件 一个进程需要向另一个或一组进程发送消息 通知它 们 发生了某种事件 如进程终止时要通知父进程 D 资源共享 多个进程之间共享同样的资源 为了做到这一点 需要内核提供锁和同步机制 E 进程控制 有些进程希望完全控制另一个进程的执行 如Debug进程 此时控制进程希望能够拦截另一个进程的所有陷入和异常 并能够及时知道它的状态改变 2019 12 19 2 进程间通信的方式 linux下的进程通信手段基本上是从Unix平台上的进程通信手段继承而来的 而对Unix发展做出重大贡献的两大主力AT T的贝尔实验室及BSD 加州大学伯克利分校的伯克利软件发布中心 在进程间通信方面的侧重点有所不同 前者对Unix早期的进程间通信手段进行了系统的改进和扩充 形成了 systemVIPC 通信进程局限在单个计算机内 后者则跳过了该限制 形成了基于套接口 socket 的进程间通信机制 Linux则把两者继承了下来 其中 最初UnixIPC包括 管道 FIFO 信号 SystemVIPC包括 SystemV消息队列 SystemV信号量 SystemV共享内存区 PosixIPC包括 Posix消息队列 Posix信号量 Posix共享内存区 2019 12 19 3 Linux进程通信方式 linux下进程间通信的几种主要手段简介 1 管道 Pipe 及有名管道 namedpipe 管道可用于具有亲缘关系进程间的通信 有名管道克服了管道没有名字的限制 因此 除具有管道所具有的功能外 它还允许无亲缘关系进程间的通信 2 信号 Signal 信号是比较复杂的通信方式 用于通知接受进程有某种事件发生 除了用于进程间通信外 进程还可以发送信号给进程本身 linux除了支持Unix早期信号语义函数signal外 还支持语义符合Posix 1标准的信号函数sigaction 2019 12 19 4 Linux进程通信方式 3 报文 Message 队列 消息队列 消息队列是消息的链接表 有足够权限的进程可以向队列中添加消息 被赋予读权限的进程则可以读走队列中的消息 消息队列克服了信号承载信息量少 管道只能承载无格式字节流以及缓冲区大小受限等缺点 4 共享内存 使得多个进程可以访问同一块内存空间 是最快的可用IPC形式 是针对其他通信机制运行效率较低而设计的 往往与其它通信机制 如信号量结合使用 来达到进程间的同步及互斥 5 信号量 semaphore 主要作为进程间以及同一进程不同线程之间的同步手段 2019 12 19 5 第四章进程间通信 管道和信号 1 2 进程间通信 PIPE 进程间通信 FIFO 3 信号中断处理 管道 管道的实质是一个内核缓冲区 进程以先进先出的方式从缓冲区中存取数据 管道一端的进程顺序地将数据写入缓冲区 另一端的进程则顺序地读出数据 该缓冲区可以看作是一个循环队列 读和写的位置都是自动增加的 不能随意改变 一个数据只能被读一次 读出以后在缓冲区中就不复存在了 当缓冲区读空或写满时 有一定的规则控制相应的读进程或写进程是否进入等待队列 当空的缓冲区有新数据写入或满的缓冲区有数据读出时 就唤醒等待队列中的进程继续读写 2019 12 19 7 管道 管道实际上以类似文件的方式与进程交互 但它并不与磁盘打交道 所以效率要比文件操作高很多 它有两个局限性 1 支持半双工 2 只有具有亲缘关系的进程之间才能使用这种无名管道 使用管道的注意事项 1 当读一个写端已经关闭的管道时 在所有数据被读取之后 read函数返回值为0 以指示到了文件结束处 2 如果写一个读端关闭的管道 则产生SIGPIPE信号 如果忽略该信号或者捕捉该信号并处理程序返回 则write返回 1 errno设置为EPIPE 2019 12 19 8 管道示例 例如 ls more功能是将ls命令的输出作为more命令的输入 并显示more的最终输出 这里ls与more要由两个进程来完成 这两个进程的通信就通过父进程shell创建管道 ls向管道输入数据 more从管道读出数据 2019 12 19 9 创建无名管道 externintpipt int pipedes 2 此函数的参数是一个整型数组 如果执行成功 pipe将存储两个整形文件描述符于 pipedes数组中 它们分别指向管道的两端 如果系统调用失败 将返回 1 2019 12 19 10 例 父子进程通过无名管道通信 include include include include include includemain pid tresult intr num intpipe fd 2 charbuf r 100 buf w 100 memset buf r 0 sizeof buf r 2019 12 19 11 例 父子进程通过无名管道通信 if pipe pipe fd 0 printf childprocesshasread dcharactersfromthepipe thestringis s n r num buf r close pipe fd 0 exit 0 2019 12 19 12 例 父子进程通过无名管道通信 else close pipe fd 0 printf pleaseinputthestring scanf s buf w if write pipe fd 1 buf w strlen buf w 1 printf parentprocesshaswritten stothepipe n buf w close pipe fd 1 waitpid result NULL 0 exit 0 2019 12 19 13 dup externintdup int fd dup 会复制一份原来已经打开的文件描述符 新的描述符指向系统文件表中下一个可用的最小非负文件描述符 它与原来的文件描述符共享同一个文件指针 并拥有相同的文件权限及模式 当调用dup 时 总返回下一个最小的可用文件描述符 例如 下面语句即可以将输出重定向到管道 intf des 2 pipe f des close fileno stdout dup f des 1 此后 所有写向标准输出的数据都将写入到管道中 因此 要复制标准输出输入设备 应先关闭这一设备 然后再复制 2019 12 19 14 复制文件描述符 2019 12 19 15 dup2 externintdup2 int fd int fd2 dup2 有两个参数 fd和fd2 fd2是小于文件描述符的最大允许值的非负整数 如果fd2是一个已打开的文件描述符 则首先关闭该文件 然后再复制 2019 12 19 16 综合应用举例 include include include include include defineDEF PAGER bin more defineMAXLINE10main intargc char argv intn intfd 2 pid tpid char pager argv0 charline MAXLINE FILE fp 2019 12 19 17 综合应用举例 if argc 2 printf errorusage n exit EXIT FAILURE if fp fopen argv 1 r NULL perror open exit EXIT FAILURE if pipe fd 0 perror pipe exit EXIT FAILURE if pid fork 0 perror fork exit EXIT FAILURE 2019 12 19 18 综合应用举例 if pid 0 close fd 0 while fgets line MAXLINE fp NULL n strlen line if write fd 1 line n n perror write exit EXIT FAILURE close fd 1 if waitpid pid NULL 0 0 perror wait exit EXIT FAILURE exit 0 2019 12 19 19 综合应用举例 else close fd 1 if fd 0 STDIN FILENO if dup2 fd 0 STDIN FILENO STDIN FILENO perror dup exit EXIT FAILURE close fd 0 if pager getenv PAGER NULL pager DEF PAGER if argv0 strrchr pager NULL argv0 elseargv0 pager if execl pager argv0 char 0 0 perror exec exit EXIT FAILURE exit 0 2019 12 19 20 流重定向 externFILE popen constchar command constchar modes popen函数创建一个子进程 并在子进程中执行第一个参数程序 同时返回一个文件指针 即第一个参数 command指向要执行的命令的指针 第二个参数表示I O模式的类型 如果此命令的输出将作为其他命令的输入 即输出重定向 则需要设置其第二个参数为 r 权限 如果此命令的输入数据要从其他命令的输出数据 即输入重定向 则需要设置其第二个参数为 w 权限 在使用完重定向后 需要使用pclose 关闭相应的流对象 该函数声明如下 externintpclose FILE stream 2019 12 19 21 例 流重定向的应用 include include include include include definePAGER PAGER more defineMAXLINE10main intargc char argv charline MAXLINE FILE fpin fpout if argc 2 printf errorusage n exit EXIT FAILURE 2019 12 19 22 例 流重定向的应用 if fpin fopen argv 1 r NULL perror open exit EXIT FAILURE if fpout popen PAGER w NULL perror popen exit EXIT FAILURE while fgets line MAXLINE fpin NULL if fputs line fpout EOF perror fputs exit EXIT FAILURE if pclose fpout 1 perror pclose exit EXIT FAILURE exit 0 2019 12 19 23 注意事项 1 如果所有指向管道写端的文件描述符都关闭了 而仍然有进程从管道的读端读数据 那么管道中剩余的数据都被读取后 再次read会返回0 就像读到文件末尾一样 2 如果有指向管道写端的文件描述符没有关闭 而持有管道写端的进程也没有向管道中写数据 这时有进程从管道读端读数据 那么管道中剩余的数据都被读取后 再次read会阻塞 直到管道中有数据可读了才读取数据并返回 3 如果所有指向管道读端的文件描述符都关闭了 这时有进程向管道的写端write 那么该进程会收到信号SIGPIPE 通常会导致进程异常终止 2019 12 19 24 注意事项 4 如果有指向管道读端的文件描述符没有关闭 而持有管道读端的进程也没有从管道中读数据 这时有进程向管道写端写数据 那么在管道被写满时再次write会阻塞 直到管道中有空位置了才写入数据并返回 5 两个进程通过一个管道只能实现单向通信 如果有时候也需要子进程写父进程读 就必须另开一个管道 2019 12 19 25 第8章进程间通信 管道和信号 1 2 进程间通信 PIPE 进程间通信 FIFO 3 信号中断处理 FIFO FIFO就是命名管道 或有名管道 它同样是基于VFS 对应的文件类型就是FIFO文件 可以通过mknod命令在磁盘上创建一个FIFO文件 当进程想通过该FIFO来通信时就可以标准的APIopen close read write unlink等 打开该文件 然后开始读写操作 对于FIFO的读写实现 它与pipe是相同的 区别在于 FIFO有open这一操作 而pipe是在调用pipe这个系统调用时直接创建了一对文件描述符用于通信 并且 FIFO的open操作还有些细致的地方要考虑 例如如果写者先打开 尚无读者 那么肯定是不能通信了 所以就需要先去睡眠等待读者打开该FIFO 反之对读者亦然 2019 12 19 27 用途 FIFO由shell命令使用以便将数据从一条管道线传送到另一条 为此无需创建中间临时文件 FIFO用于客户进程 服务器进程应用程序中 以在客户进程和服务器进程之间传递数据 2019 12 19 28 创建FIFO CreateanewFIFOnamedPATH withpermissionbitsMODE externintmkfifo comstchar path mode t mode mkfifo 会根据参数建立特殊的有名管道文件 该文件必须不存在 而参数mode为该文件的授权 mkfifo 建立的FIFO文件其他进程都可以用读写一般文件的方式存取 当使用open 函数打开FIFO文件时 O NONBLOCK会有影响 如果执行成功将返回0 否则返回 1 失败原因存储于errno中 2019 12 19 29 例 命名管道的使用 include include include include include defineFIFO tmp fifo main pid tpid charbuffer 80 intfd unlink FIFO mkfifo FIFO 0744 2019 12 19 30 例 命名管道的使用 if pid fork 0 chars Hello fd open FIFO O WRONLY printf thisisfatherwritedatais s n s printf father spidis d n getpid write fd s sizeof s close fd exit 0 2019 12 19 31 例 命名管道的使用 elseif pid 0 sleep 2 fd open FIFO O RDONLY read fd buffer 80 printf thisischildreaddatais s n buffer close fd printf child spidis d n getpid exit 0 2019 12 19 32 管道基本特点总结 两类型管道具有以下特点 1 管道是特殊类型的文件 在满足先入先出的原则条件下可能进行读写 但不能定位读写位置 2 管道是单向的 要实现双向 需要两个管道 无名管道只能实现亲缘关系进程间通信 即无名管道的两个文件描述符可以被两者都访问到 而有名管道以磁盘文件的方式存在 可以实现本机任意两进程间通信 2019 12 19 33 管道基本特点总结 续 3 无名管道阻塞问题 无名管道无须显式打开 创建时直接返回文件描述符 而在读写时需要确实对方的存在 否则将退出 即如果当前进程向无名管道的一端写数据时 必须确定其另一端为某个进程 这个进程可以是当前进程 拥有 如果写入无名管道的数据超过其最大值 写操作将阻塞 如果管道中没有数据 读操作将阻塞 如果管道发现另一端断开 另一端文件描述符关闭 将自动退出 2019 12 19 34 管道基本特点总结 续 4 有名管道阻塞问题 有名管道在打开时需要确实对方的存在 否则将阻塞 即以读方式打开某管道 该操作得以继续执行的条件是 在此之前 已经有一个进程以写的方式打开此管道 否则阻塞 直到条件满足 因此有名管道将阻塞在打开位置 也可以以读写 O RDWR 方式打开有名管道 进程能够继续执行 不阻塞 即当前进程读 当前进程写 2019 12 19 35 第8章进程间通信 管道和信号 1 2 进程间通信 PIPE 进程间通信 FIFO 3 信号中断处理 信号概述 信号是Linux系统中用于进程之间相互通信或操作的一种机制 信号可以在任何时候发给某一进程 而无需知道该进程的状态 如果该进程当前并未处于执行状态 则该信号就由内核保存起来 直到该进程恢复执行并传递给它为止 如果一个信号被进程设置为阻塞 则该信号的传递被延迟 直到其阻塞被取消时才被传递给进程 进程之间可以互相通过系统调用kill发送软中断信号 内核也可以因为内部事件而给进程发送信号 通知进程发生了某个事件 信号机制除了基本通知功能外 还可以传递附加信息 2019 12 19 37 Linux信号 2019 12 19 38 comefromasm signal h 常见的信号 Linux系统中常见的信号说明如下 1 SIGHUP 用户从终端注销时 所有已启动的进程都将收到SIGHUP信号 系统缺省状态下对该信号的处理就是中止进程 2 SIGINT 程序终止信号 在程序运行过程中 用户通过键盘按下 Ctrl C 键将产生该信号 3 SIGQUIT 程序退出信号 在程序运行过程中 用户通过按下 Ctrl 键将产生该信号 4 SIGBUS和SIGSEGV 进程访问非法地址时 引发该信号 5 SIGFPE 进行算术运算中出现致命错误 如除零操作 数据溢出等 2019 12 19 39 常见的信号 续 6 SIGKILL 终止用户进程执行的信号 在shell下通过执行 kill 9 命令发送的就是该信号 7 SIGTERM 进程结束信号 在shell下执行 kill进程pid 命令发送的就是该信号 8 SIGALRM 定时器信号 9 SIGCLD 子进程退出信号 如果父进程没有忽略该信号 也没有处理该信号 则子进程退出后将形成僵尸进程 2019 12 19 40 信号的分类 可靠信号 也称为实时信号 支持排队 不可靠信号 非实时信号 不支持排队 发送用户进程判断后注册 发现相同信号已经在进程中注册 就不再注册 忽略该信号 2019 12 19 41 可能的信号来源 信号是在软件层次上对中断机制的一种模拟 是一种异步通信方式 信号可以在用户空间进程和内核之间直接交互 内核也可以利用信号来通知用户空间的进程发生了哪些系统事件 信号事件的发生有两个来源 1 硬件来源 用户按某些终端键时将产生信号 如CTRL C将产生SIGINT 中止信号 硬件异常产生信号 如除数为0或无效的存储访问等 2 软件来源 终止进程信号 其他进程调用kill函数 将信号发送个另一个进程或进程组 软件异常产生信号 2019 12 19 42 信号的处理流程 1 信号被某个进程产生 并设置此信号传递的对象 一般为对应进程的pid 然后传递给操作系统 2 操作系统根据接收进程的设置 是否阻塞 而选择性的发送给接收者 如果接收者阻塞该信号 且该信号是可以阻塞的 操作系统将暂时保留该信号 而不传递 直到该进程解除对此信号的阻塞 如果对应进程已经退出 则丢弃此信号 如果对应进程没有阻塞 操作系统将传递此信号 3 目的进程接收到此信号后 将根据当前进程对此信号设置的预处理方式 暂时终止当前代码的执行 保护上下文 主要包括临时寄存器数据 当前程序位置以及当前CPU的状态 转而执行中断服务程序 执行完成后再恢复到被中断的位置 当然 对于可抢占式内核 在中断返回时还将引发新的调度 2019 12 19 43 信号的生命周期 信号处理 信号产生 信号注册 信号注销 内核进程 用户进程 2019 12 19 44 kill产生一个信号 kill 函数用来向指定进程发送一个信号 此函数声明如下 comefrom usr include signal hexternintkill pid t pid int sig 此函数的第一个参数为要传递信号的进程号 PID 第二个参数即发送的信号值 pid可以取以下几种值 pid o 将信号发送给进程的PID值为pid的进程 pid 0 将信号发送给和当前进程在同一进程组的所有进程 pid 1 将信号发送给系统内的所有进程 pid 0 将信号发送给进程组号PGID为pid绝对值的所有进程 如果成功完成返回值0 否则返回 1 并设置errno以指示错误 2019 12 19 45 include includevoidmain intargc char argv intpid signo if argc 3 printf usage killsenderpidsigno n return sscanf argv 1 d 2019 12 19 46 例 编写程序killsender 通过kill系统调用向指定进程 pid 发送信号 raise自举一个信号 raise 函数用来给当前进程发送一个信号 即唤醒一个进程 此函数声明如下 comefrom usr include signal h RaisesignalSIG i e sendSIGtoyourself externintraise int sig 此函数相当于采用以下方式执行kill 函数 if kill getpid int sig 1 perror raise 2019 12 19 47 例 设计一个程序 创建一个子进程 父进程向子进程发出信号 子进程收到此信号 结束子进程的运行 include include include include includeintmain pid tresult intret result fork intnewret 2019 12 19 48 if result 0 perror fork exit EXIT FAILURE elseif result 0 raise SIGSTOP exit 0 else printf child spid d n result if waitpid result NULL WNOHANG 0 if ret kill result SIGKILL 0 printf killfunctionfinished dprocesswithreturnvalue d n result ret else perror kill 2019 12 19 49 alarm 定时 alarm 函数用来传递定时信号 即在多少时间内产生SIGALRM信号 此函数每调用一次 产生一个信号 并不是循环产生SIGALRM信号 comefrom usr include unistd hexternunsignedintalarm unsignedint seconds 此函数只有一个参数 即在多少时间 秒 内发送SIGALRM信号给当前进程 默认情况下 当进程接受到alarm信号后将终止执行 如果sec为0 则取消所有先前发出的报警请求 如果在调用alarm 函数前没有调用过alarm 函数 如果执行成功 将返回0 否则返回 1 并置errno标致错误 2019 12 19 50 例 alarm的使用 include includeintmain printf firsttimereturn d n alarm 4 sleep 1 printf aftersleep 1 remain d n alarm 2 printf renewalarm remain d n alarm 1 2019 12 19 51 ualarm定时 ualarm将使当前进程在指定时间 第一个参数 以us为单位 内产生SIGALRM信号 然后每隔指定时间 第二个参数 以us为单位 重复产生SIGALRM信号 如果执行成功将返回0 该函数声明如下 extern useconds tualarm useconds t value useconds t interval 2019 12 19 52 信号处理与signal安装信号 信号处理办法 1 忽略此信号 大多数信号都可使用这种方式进行处理 但有两种信号不能被忽略 SIGKILL和SIGSTOP 这两种信号不能被忽略的原因是 它们向超级用户提供一种使进程终止或停止的可靠方法 2 捕捉信号 通知内核在某种信号发生时调用一个用户函数 在用户函数中 可执行用户希望对这种事件进行的处理 这需要安装此信号 例如捕捉到SIGCHLD信号 则表示子进程已经终止 所以此信号的捕捉函数可以调用waitpid 以取得该子进程的进程PID以及它的终止状态和资源 3 执行系统默认操作 Linux系统对任何一个信号都规定了一个默认的操作 2019 12 19 53 signal安装信号 typedefvoid sighandler t int extern sighander tsignal int sighandler t handler 此函数有两个参数 第一个参数sig为接收到的信号 第二个参数为接收到此信号后的处理代码入口或下面几个宏 Fakesignalfunctions defineSIG ERR sighandler t 1 Errorreturn defineSIG DFL sighandler t 0 Defaultaction defineSIG IGN sighandler t 1 Ignoresignal 2019 12 19 54 例 编写程序 killrecerver和killsender 其中killrecerver用于接收SIGUSR1 值为10 信号 而killsender通过kill系统调用向指定进程 pid 发送信号 include include include include SIGUSR1信号处理函数voidCbSigUsr1 intsigno 输出接收到的信号信息printf nreceivesignal d n signo 2019 12 19 55 voidmain 安装SIGUSR1信号if signal SIGUSR1 CbSigUsr1 SIG ERR perror signal return printf mypidis d n getpid printf waitingforSIGUSR1 n 暂停 等待信号pause 2019 12 19 56 例 signal的应用 include include include includevoidfun ctrl c intmain void signal SIGINT fun ctrl c printf NowI mstarting n while 1 printf thisisaendlessloopunlessCtrl carepressd n sleep 2 exit 0 2019 12 19 57 例 signal的应用 voidfun ctrl c printf tCtrl cwerepressed n printf tThisisjustanexampleforsignalfunction n printf tresetsignalSIGINT n void signal SIGINT SIG DFL 2019 12 19 58 sigaction安装信号 externintsigaction int sig structsigaction act structsigaction oact 此函数的第一个参数为接收到的信号 第二 三个参数均为信号结构sigaction 用于描述要采取的操作及相关信息 见后续说明 变量 第二个参数用来指定欲设置的信号处理信息 第三个参数将返回执行此程序前信号处理信息 如果第二个参数act不为空指针 则指定信号关联的操作为此参数指向的结构 如果参数oact不为空指针 则用来存储以前设置的与此信号关联的操作 如果参数act为空指针 则信号处理保持不变 因此 该调用可用于询问对指定信号的当前处理 2019 12 19 59 structsigaction Structsigaction union sighandler t sa handler void sa sigaction int structsiginfo void u sigset tsa mask unsignedlongsa flags void sa restorer void definesa handler u sa handler definesa sigaction u sa sigaction 2019 12 19 60 例 sigaction的应用 include include includevoidmyhandler intsig intmain structsigactionact oact act sa handler myhandler sigemptyset 2019 12 19 61 voidmyhandler intsig printf thesignal dwascaught n sig 信号集与屏蔽信号 中断是可以被屏蔽 阻塞 的 部分硬件中断是必须立即处理的 例如复位中断 因此 Linux的信号是可以屏蔽 即阻塞信号 但这与前面提到的忽略是有区别的 信号忽略 系统仍然传递该信号 只是相应进程对该信号不作任何处理而已 信号阻塞 系统不传递该信号 显示该进程无法接收到该信号直到进程的信号集发生改变 20
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 部队培训安全保密协议课件
- 社区服务边缘智能应用-洞察及研究
- 湖北省黄石市大冶市2024-2025学年七年级下学期期末考试数学试卷(含答案)
- 安徽省黄山市2024-2025学年高二上学期期末质量检测物理试卷(含答案)
- 部门安全培训需求课件
- 遨游汉字王国课件
- 基于循环经济理念的分条带钢边角料高值化再利用工艺创新图谱
- 基于代谢组学的前列康片多靶点作用机制网络图谱构建
- 培养基配方迭代与专利壁垒下的中小企业研发困境
- 国际标准体系下高强浇注料出口认证壁垒突破与质量追溯体系重构
- 南通市事业单位招聘笔试真题2024
- 铁路设备企业数字化转型与智慧升级战略研究报告
- 化妆工具、彩妆产品的认识及用途
- 电梯自动化与智能化技术的前沿探索
- 物料计划控制管理
- 2025年万达商业地产租赁合同标准版
- 感染性腹泻病例演示文档
- 涂塑钢管焊接施工方案
- DB21-T 4079-2024 畜禽养殖场污水贮存设施建设规范
- 诚信培训教育课件
- 人教版八年级上册历史的知识点
评论
0/150
提交评论