linux信号与系统调用的关系

合集下载

国家开放大学《操作系统》形考任务1答案

国家开放大学《操作系统》形考任务1答案

一、单选题为了使系统中所有的用户都能得到及时的响应,该操作系统应该是(分时系统)。

为用户分配主存空间,保护主存中的程序和数据不被破坏,提高主存空间的利用率。

这属于(存储管理)。

为了描述进程的动态变化过程,采用了一个与进程相联系的(进程控制块),根据它而感知进程的存在。

以下著名的操作系统中,属于多用户、分时系统的是(UNIX系统)。

以下不属于操作系统具备的主要功能的是(文档编辑)。

以下不属于进程高级通信方式的是(进程互斥和同步方式)。

下列关于引入线程的好处的描述中,不正确的是(利于分配资源)。

下列进程状态的转换中,不正确的是(从就绪到阻塞)。

下列关于进程和线程的叙述中,正确的是(一个进程可拥有若干个线程)下列系统中,属于实时系统的是(火车订票系统)。

在下列操作系统中,强调吞吐能力的是(多道批处理系统)。

在一段时间内,只允许一个进程访问的资源称为(临界资源)。

在分时系统中,时间片一定,则(用户数越多),响应时间越长。

在计算机系统中,操作系统是(处于裸机之上的第一层软件)。

在单处理机系统中,处于运行状态的进程(只有一个)。

在操作系统中引入“进程”概念的主要目的是(描述程序动态执行过程的性质)。

在操作系统中,进程的最基本的特征是(动态性和并发性)。

在进程通信中,使用信箱方式交换信息的是(消息传递方式)。

在执行V操作时,当信号量的值(小于等于0 ),应释放一个等待该信号量的进程。

UNIX命令的一般格式是(命令名[选项] [参数] )。

UNIX操作系统核心层的实现结构设计采用的是(层次结构)。

现代操作系统的基本特征是(程序的并发执行)、资源共享和操作的异步性。

现代操作系统中引入线程以后,进程(只是资源分配的单位)。

系统调用是由操作系统提供的内部调用,它(只能通过用户程序间接使用)。

系统出现死锁的原因是(若干进程因竞争资源而无休止地循环等待着,而且都不释放已占有的资源)。

操作系统对缓冲区的管理属于(设备管理)的功能。

linux操作系统的结构及详细说明

linux操作系统的结构及详细说明

linux操作系统的结构及详细说明linux的操作系统的结构你了解多少呢?下面由店铺为大家整理了linux操作系统的结构及详细说明的相关知识,希望对大家有帮助!linux操作系统的结构及详细说明:一、 linux内核内核是操作系统的核心,具有很多最基本功能,它负责管理系统的进程、内存、设备驱动程序、文件和网络系统,决定着系统的性能和稳定性。

Linux 内核由如下几部分组成:内存管理、进程管理、设备驱动程序、文件系统和网络管理等。

系统调用接口:SCI 层提供了某些机制执行从用户空间到内核的函数调用。

这个接口依赖于体系结构,甚至在相同的处理器家族内也是如此。

SCI 实际上是一个非常有用的函数调用多路复用和多路分解服务。

在 ./linux/kernel 中您可以找到 SCI 的实现,并在 ./linux/arch 中找到依赖于体系结构的部分。

1. 内存管理对任何一台计算机而言,其内存以及其它资源都是有限的。

为了让有限的物理内存满足应用程序对内存的大需求量,Linux 采用了称为“虚拟内存”的内存管理方式。

Linux 将内存划分为容易处理的“内存页”(对于大部分体系结构来说都是 4KB)。

Linux 包括了管理可用内存的方式,以及物理和虚拟映射所使用的硬件机制。

不过内存管理要管理的可不止 4KB 缓冲区。

Linux 提供了对 4KB 缓冲区的抽象,例如 slab 分配器。

这种内存管理模式使用 4KB 缓冲区为基数,然后从中分配结构,并跟踪内存页使用情况,比如哪些内存页是满的,哪些页面没有完全使用,哪些页面为空。

这样就允许该模式根据系统需要来动态调整内存使用。

为了支持多个用户使用内存,有时会出现可用内存被消耗光的情况。

由于这个原因,页面可以移出内存并放入磁盘中。

这个过程称为交换,因为页面会被从内存交换到硬盘上。

内存管理的源代码可以在 ./linux/mm 中找到。

2 .进程管理进程实际是某特定应用程序的一个运行实体。

Linux内核中系统调用详解

Linux内核中系统调用详解

Linux内核中系统调用详解什么是系统调用?(Linux)内核中设置了一组用于实现各种系统功能的子程序,称为系统调用。

用户可以通过系统调用命令在自己的应用程序中调用它们。

从某种角度来看,系统调用和普通的函数调用非常相似。

区别仅仅在于,系统调用由(操作系统)核心提供,运行于核心态;而普通的函数调用由函数库或用户自己提供,运行于用户态。

随Linux核心还提供了一些(C语言)函数库,这些库对系统调用进行了一些包装和扩展,因为这些库函数与系统调用的关系非常紧密,所以习惯上把这些函数也称为系统调用。

为什么要用系统调用?实际上,很多已经被我们习以为常的C语言标准函数,在Linux 平台上的实现都是靠系统调用完成的,所以如果想对系统底层的原理作深入的了解,掌握各种系统调用是初步的要求。

进一步,若想成为一名Linux下(编程)高手,也就是我们常说的Hacker,其标志之一也是能对各种系统调用有透彻的了解。

即使除去上面的原因,在平常的编程中你也会发现,在很多情况下,系统调用是实现你的想法的简洁有效的途径,所以有可能的话应该尽量多掌握一些系统调用,这会对你的程序设计过程带来意想不到的帮助。

系统调用是怎么工作的?一般的,进程是不能访问内核的。

它不能访问内核所占内存空间也不能调用内核函数。

(CPU)(硬件)决定了这些(这就是为什么它被称作"保护模式")。

系统调用是这些规则的一个例外。

其原理是进程先用适当的值填充(寄存器),然后调用一个特殊的指令,这个指令会跳到一个事先定义的内核中的一个位置(当然,这个位置是用户进程可读但是不可写的)。

在(Intel)CPU中,这个由中断0x80实现。

硬件知道一旦你跳到这个位置,你就不是在限制模式下运行的用户,而是作为操作系统的内核--所以你就可以为所欲为。

进程可以跳转到的内核位置叫做sysem_call。

这个过程检查系统调用号,这个号码告诉内核进程请求哪种服务。

然后,它查看系统调用表(sys_call_table)找到所调用的内核函数入口地址。

Linux操作系统 考试题库

Linux操作系统 考试题库

1.在Linux目录结构中目录中的文件是普通用户可以使用的可使用的可执行文件的目录是(B)19A./sbinB./binC./usrD./lib2.在Linux目录结构中Linux的内核及引导程序所需要的文件位于(B)目录A/bin B./boot C。

/root D./proc3.在Linux目录结构中用来存放系统配置文件(D)目录A./libB./devC./proc D。

/etc4.Linux三种特殊权限中仅用于目录文件的权限是(C)22A.SUIDB.SGID C。

黏滞位 D.都可以5.Linux三种权限中允许进入目录的权限(C) 22A。

r—可读 B.w-可写C。

x—可执行D。

都不是6.下列脚本文件最先自动执行的是(A)24A./etc/rc.local B。

/etc/profile C.~/。

bashrc D.~/.bash_logout7.下面通配符可匹配多个任意字符的通配符是(A)29A.*B. ? C。

[abcde ] D.[!a—e]8.输出重定向符号右边的文件已经存在,不会覆盖文件而是追加的定向符是(B)A.> B。

> > C. 2> D。

&〉9.表示用户家目录的是(B)A./home (所有用户家目录的父目录,+用户名才是用户家目录) B。

~C。

. D。

10.可删除非空目录及其子目录的命令是(B)A。

touch B.rm -r C。

mkdir D.rmdir空目录11. 是强引用的符号(A)A。

单引号 B.反引号C。

双引号 D.中括号12.可显示隐藏文件的ls命令形式选项是(A)A。

ls —a B. ls —d C。

ls -h D .ls —l13.可通过接受标准输入作为输出内容来创建简单文件的命令是(B)42A.touchB.cat C。

vi D. gedit14.不带有编辑功能但有翻页、按行滚动、搜索功能的命令是(B)43A.cat B。

24秋国家开放大学操作系统形考任务1-4参考答案

24秋国家开放大学操作系统形考任务1-4参考答案

国家开放大学《操作系统》形考任务1-4参考答案题目顺序随机,下载后可利用查找功能完成学习任务形考作业1一、单项选择题1.按照所起的作用和需要的运行环境,操作系统属于()。

A. 系统软件B. 应用软件C. 用户软件D. 支撑软件2.UNIX操作系统核心层的实现结构设计采用的是()。

A. 层次结构B. 网状结构C. 微内核结构D. 单块式结构3.UNIX命令的一般格式是()。

A. [参数] [选项] 命令名B. [选项] [参数] 命令名C. [命令名] [选项] [参数]D. 命令名[选项] [参数]4.操作系统的基本职能是()。

A. 提供方便的可视化编辑程序B. 提供功能强大的网络管理工具C. 提供用户界面,方便用户使用D. 控制和管理系统内各种资源,有效地组织多道程序的运行5.操作系统对缓冲区的管理属于()的功能。

A. 处理器管理B. 存储器管理C. 文件管理D. 设备管理6.操作系统内核与用户程序、应用程序之间的接口是()。

A. C语言函数B. shell命令C. 图形界面D. 系统调用7.工业过程控制系统中运行的操作系统最好是()。

A. 实时系统B. 分时系统C. 网络系统D. 分布式操作系统8.进程从运行状态变为阻塞状态的原因是()。

A. 输入或输出事件发生B. 输入或输出事件完成C. 时间片到D. 某个进程被唤醒9.进程控制块是描述进程状态和特性的数据结构,一个进程()。

A. 可以没有进程控制块B. 可以有多个进程控制块C. 可以和其他进程共用一个进程控制块D. 只能有唯一的进程控制块10.进程与程序之间有密切联系,但又是不同的概念。

二者的一个本质区别是()。

A. 程序保存在文件中,进程存放在内存中B. 程序是动态概念,进程是静态概念C. 程序顺序执行,进程并发执行D. 程序是静态概念,进程是动态概念11.两个进程合作完成一个任务,在并发执行中,一个进程要等待其合作伙伴发来信息,或者建立某个条件后再向前执行,这种关系是进程间的()关系。

操作系统实验-进程控制

操作系统实验-进程控制

实验一、进程控制实验1.1 实验目的加深对于进程并发执行概念的理解。

实践并发进程的创建和控制方法。

观察和体验进程的动态特性。

进一步理解进程生命期期间创建、变换、撤销状态变换的过程。

掌握进程控制的方法,了解父子进程间的控制和协作关系。

练习 Linux 系统中进程创建与控制有关的系统调用的编程和调试技术。

1.2 实验说明1)与进程创建、执行有关的系统调用说明 进程可以通过系统调用fork()创建子进程并和其子进程并发执行.子进程初始的执行映像是父进程的一个复本.子进程可以通过 exec()系统调用族装入一个新的执行程序。

父进程可以使用 wait()或 waitpid()系统调用等待子进程的结束并负责收集和清理子进程的退出状态。

fork()系统调用语法:pid_t#include <unistd.h>fork(void);fork 成功创建子进程后将返回子进程的进程号,不成功会返回-1.exec 系统调用有一组 6 个函数,其中示例实验中引用了 execve 系统调用语法:#include <unistd.h>const char * envp[]);path 要装const char *argv[],int execve(const char *path,入的新的执行文件的绝对路径名字符串.argv[] 要传递给新执行程序的完整的命令参数列表(可以为空).envp[] 要传递给新执行程序的完整的环境变量参数列表(可以为空).Exec 执行成功后将用一个新的程序代替原进程,但进程号不变,它绝不会再返回到调用进程了。

如果 exec 调用失败,它会返回-1。

wait() 系统调用语法:#include <sys/types.h>pid_t#include <sys/wait.h>wait(int *status);status 用pid_t waitpid(pid_t pid,int *status,int option);于保留子进程的退出状态pid 可以为以下可能值:-1 等待所有 PGID 等于 PID 的绝对值的子进程1 等待所有子进程0 等待所有 PGID 等于调用进程的子进程>0 等待 PID 等于 pid 的子进程 option 规定了调用 waitpid 进程的行为:WNOHANG 没有子进程时立即返回WUNTRACED 没有报告状态的进程时返回wait 和 waitpid 执行成功将返回终止的子进程的进程号,不成功返回-1。

Linux 信号说明列表

Linux 信号说明列表

$ kill -l1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR213) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+136) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+540) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+944) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+1348) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-1352) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-956) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-560) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-164) SIGRTMAX列表中,编号为1 ~ 31的信号为传统UNIX支持的信号,是不可靠信号(非实时的),编号为32 ~ 63的信号是后来扩充的,称做可靠信号(实时信号)。

Linux命令高级技巧使用strace命令跟踪系统调用和进程活动

Linux命令高级技巧使用strace命令跟踪系统调用和进程活动

Linux命令高级技巧使用strace命令跟踪系统调用和进程活动strace命令是Linux系统下用于调试和跟踪程序执行的工具,它可以捕捉程序与操作系统之间的交互信息,包括系统调用和信号传递等。

通过strace命令的使用,我们可以深入了解程序的执行过程,排查问题,进行性能优化等。

本文将详细介绍如何使用strace命令进行系统调用跟踪和进程活动跟踪,并通过实际案例演示其高级技巧。

## 1. strace命令简介strace命令是一个功能强大的系统调用跟踪工具,它可以监视和记录程序执行过程中的系统调用和信号传递等交互信息。

strace命令可以捕捉到程序的系统调用参数、返回值和执行时间等关键信息,帮助开发者深入理解程序的执行流程,并发现潜在的问题。

## 2. 基本用法在使用strace命令时,通常需要指定待跟踪的目标程序,并可以设置一些选项进行进一步的控制。

下面是一些常用的基本用法:- 跟踪指定程序的系统调用:`strace <program>`- 将输出重定向到文件:`strace -o <output_file> <program>`- 显示系统调用号:`strace -e trace=<syscall> <program>`- 显示系统调用参数和返回值:`strace -e trace=<syscall> -v<program>`- 显示系统调用参数和执行时间:`strace -e trace=<syscall> -T<program>`通过上述基本用法,我们可以轻松地进行程序的系统调用跟踪,并获取所需的关键信息。

## 3. 实例演示为了更好地理解strace命令的使用,接下来将通过一个实际案例进行演示。

假设我们有一个待跟踪的程序test,我们可以通过以下步骤使用strace命令进行跟踪:1. 编译程序,并生成可执行文件test。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

信号与系统调用的关系:当一个进程正在执行一个系统调用时,如果向该进程发送一个信号,那么对于大多数系统调用来说,这个信号在系统调用完成之前将不起作用,因为这些系统调用不能被信号打断。

但是有少数几个系统调用能被信号打断,例如:wait(),pause()以及对慢速设备(终端、打印机等)的read()、write()、open()等。

如果一个系统调用被打断,它就返回-1,并将errno 设为EINTR。

可以用下列代码来处理这种情况:if (wirte(tfd,buf,SIZE)<0) {if (errno==EINTR) {warn(“Write interrupted.”);……}}信号的复位:在Linux 中,当一个信号的信号处理函数执行时,如果进程又接收到了该信号,该信号会自动被储存而不会中断信号处理函数的执行,直到信号处理函数执行完毕再重新调用相应的处理函数。

下面的程序演示了这一点:#include<stdio.h>#include<signal.h>int catch(int sig); //信号绑定函数,必须在main函数前声明。

int main(void){printf("the program is starting.\n");signal(SIGINT, catch);//接受到SIGINT信号,执行绑定的catch函数//signal(SIGINT,SIG_DFL);//SIG_DFL 恢复成系统的缺省动作//signal(SIGINT,SIG_IGN);//告诉进程将 SIGINT 信号忽略,CTRL+Csleep(10);printf("the end.\n");return0;}int catch(int sig){printf("Interrupt called.\n");sleep(4);printf(“I nterrupt Func end.\n”);}执行它,结果如下:the program is starting.<ctrl+c>Interrupt called<ctrl+c>Interrupt Func end.Interrupt calledInterrupt Func end.the end只能保存一个CTRL+C。

如果在信号处理函数执行时进程收到了其它类型的信号,该函数的执行就会被中断:the program is starting.<ctrl+c>Interrupt called<ctrl+\>Quit calledQuit ended.Interrupt Func end。

the ended.在进程间发送信号:个进程通过对signal()的调用来处理其它进程发送来的信号。

一个进程也可以向其它的进程发送信号。

这一操作是由系统调用kill()来完成的。

kill()在linux 系统库signal.h中的函数声明:int kill(pid_t pid, int sig);参数pid 指定了信号发送的对象进程:它可以是某个进程的进程标识符(pid),也可以是以下的值:如果pid 为零,则信号被发送到当前进程所在的进程组的所有进程;如果pid 为-1 ,则信号按进程标识符从高到低的顺序发送给全部的进程(这个过程受到当前进程本身权限的限制);如果pid 小于-1,则信号被发送给标识符为pid 绝对值的进程组里的所有进程。

需要说明的是,一个进程并不是向任何进程均能发送信号的,这里有一个限制,就是普通用户的进程只能向具有与其相同的用户标识符的进程发送信号。

也就是说,一个用户的进程不能向另一个用户的进程发送信号。

只有root 用户的进程能够给任何线程发送信号。

参数sig 指定发送的信号类型。

它可以是任何有效的信号。

由于调用kill()的进程需要直到信号发往的进程的标识符,所以这种信号的发送通常只在关系密切的进程之间进行,比如父子进程之间。

下面是一个使用kill()调用发送信号的例子。

这个程序建立两个进程,并通过向对方发送信号SIGUSR1 来实现它们之间的同步。

这两个进程都处于一个死循环中,在接收对方发送的信号之前,都处于暂停等待中。

这是通过系统调用pause()来实现的,它能够使一个程序暂停,直至一个信号到达,然后进程输出信息,并用kill 发送一个信号给对方。

当用户按了中断键,这两个进程都将终止。

int ntimes=0;main(){int pid,ppid;int p_action(), c_action();/* 设定父进程的SIGUSR1 */signal(SIGUSR1,p_action);switch(pid=fork()) {case -1: /*fork 失败*/perror("synchro");exit(1);case 0: /*子进程模块*//* 设定子进程的SIGUSR1 */signal(SIGUSR1,c_action);/* 获得父进程的标识符*/ppid=getppid();for(;;) {sleep(1);kill(ppid,SIGUSR1);pause();}- 58- Linux 网络编程/*死循环*/break;default: /*父进程模块*/for (;;) {pause();sleep(1);kill(pid,SIGUSR1);}/*死循环*/}}p_action(){printf("Patent caught signal #%d\n",++ntimes); }c_action(){printf("Child caught signal #%d\n",++ntimes); }程序运行结果如下:Patent caught signal #1Patent caught signal #2Child caught signal #2Patent caught signal #3Child caught signal #3Patent caught signal #4Child caught signal #4<ctrl+c>kill 命令用于向一个运行进程发送信号,它发送的信号默认为SIGTERM,但是也可以指定为其它信号。

我们可以直接用信号的号码来指定kill 命令所发送信号之类型,也可以用符号名指定。

比如可以用下面的命令来完成向进程标识符为1234 的进程发送SIGINT 信号:kill –s SIGINT 1234系统调用alarm() 和pause():alarm()它可以建立一个进程的报警时钟,在时钟定时器到时的时候,用信号向程序报告。

alarm()系统调用在Linux 系统函数库unistd.h 中的函数声明如下:unsigned int alarm(unsigned int seconds);函数唯一的参数是seconds ,其以秒为单位给出了定时器的时间。

当时间到达的时候,就向系统发送一个SIGARLM 信号。

例如:alarm(60);这一调用实现在60 秒后发一个SIGALRM 信号。

alarm 不会象sleep 那样暂停调用进程的执行,它能立即返回,并使进程继续执行,直至指定的延迟时间到达发出SIGALRM 信号。

事实上,一个由alarm()调用设置好的报警时钟,在通过exec() 调用后,仍将继续有效。

但是,它在fork() 调用后中,在子进程中失效。

如果要使设置的报警时钟失效,只需要调用参数为零的alarm():alarm(0)alarm()调用也不能积累。

如果调用alarm 两次,则第二次调用就取代第一次调用。

但是,后一个alarm会把前一个alarm的剩余时间作为返回值,然后自己重新从0开始计数,前一个alarm就此成为历史。

当需要对某项工作设置时间限制时,可以使用alarm()调用来实现。

其基本方法为:先调用alarm()按时间限制值设置报警时钟,然后进程作某一工作。

如果进程在规定时间以内完成这一工作,就再调用alarm(0)使报警时钟失效。

如果在规定时间内未能完成这一工作,进程就会被报警时钟的SIGALRM 信号中断,然后对它进行校正。

下面这个程序使用上述方法来强制用户作出回答。

在其中包括一个quickreply()函数,它有一个参数prompt,它是一个指向提示字符串的指针。

quickreply 的返回值也是一个指针。

它指向含有输入行信息的字符串。

这个例行程序在试作五次之后,如果仍未得到输入信息,就返回一个null 指针。

每当quickreply 要提醒用户时,它就向终端发送ASCII 码007,这会使终端响铃。

quickreply 调用了标准I/O 库中的例行程序gets()。

gets()把标准输入上的下一行信息存入一个字符型数组,它返回一个指向该数组的指针。

当到达文件末或出错时,gets 则返回一个null 指针。

函数catch 是信号SIGALRM 的关联函数,它完成对此信号的处理。

catch设置了一个timed_out 标志,在quickreply 中对这个标志进行检查,看它是否超过了规定的时限。

#include <stdio.h>#define TIMEOUT 5#define MAXTRIES 5#define LINESIZE 100#define BELL '\007'#define TRUE 1#define FALSE 0/* 判断超时是否已经发生的标志*/static int time_out;static char inputline[LINESIZE];char* quickreply (char* prompt);- 60- Linux 网络编程main(){printf("%s\n",quickreply("Input"));}char* quickreply (char* prompt){int (*was)(),catch(),ntries;char* answer;/* 设定捕捉SIGALRM 的的关联并保存原有关联*/ was=signal(SIGALRM,catch);for (ntries=0;ntries<MAXTRIES;ntries++){time_out=FALSE;printf("\n%s>",prompt);/* 设定定时器*/alarm(TIMEOUT);/* 获取输入*/answer=gets(inputline);/* 关闭定时器*/alarm(0);if (!time_out)break;}/* 恢复原有的SIGALRM 关联*/signal(SIGALRM,was);return (time_out?((char*) 0):answer);}/* SIGALRM 信号处理函数*/catch(){/* 设定超时标志*/time_out=TRUE;/* 响铃警告*/putchar(BELL);}2.系统调用pause()系统调用pause()能使调用进程暂停执行,直至接收到某种信号为止。

相关文档
最新文档