unix_bishi.doc

来自「unix的笔试题/面试题」· DOC 代码 · 共 146 行

DOC
146 行
字号
1. 简述Sun Workshop中的几个重要概念:event/handler, watchpoint, RTC。 
2. 简述Solaris所实现的系统接口标准(至少两种),并说明feature test macros的功能和使用方法。 
unix 标准有:ANSI C, IEEE POSIX, X/OPEN XPG3 和 FIPS.实际应用的有:System V Release 4, 4.3+BSD. 
feature test macro: 头文件中定义了很多宏,有POSIX,XPG3的。当程序编译时如果希望只使用POSIX的定义而不使用其它定义, 
那么就需定义常数_ P O S I X _ S O U R C E。 
当该常数定义时,就能排除其它专有的定义。 
常数_ P O S I X _ S O U R C E 及其对应的常数_ X O P E N _ S O U R C E 被称之为功能测试宏(f e a t u r e 
test macro )。所有功能测试宏都以下划线开始。当要使用它们时,通常在c c 命令行中以下列方 
式定义: 
cc -D_POSIX_SOURCE file.c 
这使得在C 程序包括任何头文件之前,定义了功能测试宏。如果我们仅想使用P O S I X . 1 定义,那么也可将源文件的第一行设置为: 
#define _POSIX_SOURCE 1 
另一个功能测试宏是:_ _STDC_ _,它由符合ANSI C 标准的编译程序自动定义。 
这样就允许我们编写ANSI C 编译程序和非ANSI C 编译程序都能编译的程序。 
例如,一个头文件可能会是: 
#ifdef __STDC__ 
void *myfunc(const char *, int); 
#else 
void *myfunc(); 
#endif 

3. 试比较系统调用和库函数的区别(重点说明返回值和内存分配)。 
system call 是用户访问内核系统服务的接口,使内核为调用线程执行某种特定的功能。 
每个system call 在标准C 库中设置一个具有同样名字的函数。 
用户进程用标准C 调用序列来调用这些函数,然后,函数又用系统所要求的技术调用相应的内核服务。 
然后执行某个产生软中断进入内核的机器指令。是于平台相关的。 
library function 是将system call进行封装后提供的接口。实际上,用户也可以定制自己的library function. 
大体上,systerm call 实现内存的分配,library function 实现内存的管理。 
当 
1)library function在调用system call时,system call不会申请静态空间存放调用结果。Library function 
应该申请动态空间,将地址作为参数传入。这时,system call将结果写在动态空间中。 
2)library function在调用system call时,system call每次将结果放在固定的静态空间中。用户得到的返回值在静态空间中, 
如果用户要多次调用该函数,则应申请动态空间,将返回值拷贝到动态空间中。在下次调用时,静态空间被重新赋值。 
3)library function在调用system call时,system call每次都为用户进程申请动态空间,赋值,将动态空间地址返回给用户。 
这种情况下,需要用户在使用完后,释放内存。 
4. 简述Solaris的进程及两级线程模型,并说明概念-核心所支持的调度类。 
进程是含有一个用户程序环境的抽象,包括虚存环境、程序所需资源以及至少一个执行线程。 
每个进程中至少有一个轻量级线程,它是进程中每个内核线程的虚拟执行环境。 
轻量级进程允许进程中的每个内核线程,获得与同一进程中的其他内核线程无关的系统调用。 
虽然在统一进程内切换多个线程是不耗资源的,但线程的创建和消除却很耗资源。另外,进程中的内核线程要求有一个轻量级进程,它含有消耗内和资源的堆栈。 
因此,在每个进程中增加了一级线程管理用户线程--二级线程模型。 
见下图: 

solaris的调度类有: 
TS(分时)--它是进程和进程中所有内核线程的缺省调度类。他根据当前处理器的使用情况动态改变进程的优先级。 
进程优先级和时间量在每个时钟滴答时,或在一个I/O引起睡眠后的唤醒期间,根据分时调度表计算。TS类的优先级由0-59。 
IA(交互类,增强的TS类)--它是由桌面视窗系统使用得调度类。用来提高目的视窗中线程的优先级。 
SYS(系统类)--内核线程使用的系统类。优先级60-99 
RT(实时类)--用于实现固定的优先级、固定的时间量调度。优先级100-159 
5. 当使用vfork()创建的新进程(没有调用exec或exec不成功)要退出时,我们一般调用_exit()函数,为什么? 
v f o r k 用于创建一个新进程,而该新进程的目的是e x e c 一个新程序。v f o r k 与f o r k 一样都创建一个子进程, 
但是它并不将父进程的地址空间完全复制到子进程中,因为子进程会立即调用e x e c (或e x i t ), 
不过在子进程调用e x e c 或e x i t 之前,它在父进程的空间中运行。v f o r k 保证子进程先运行,在它调用e x e c 或e x i t 之后父进 
程才可能被调度运行。 
e x i t 和_ e x i t 函数用于正常终止一个程序:_ e x i t 立即进入内核,e x i t 则先执行一些清除处理(包括调用执行各终止处理程序,关闭所有标准I / O 流等),然后进入内核。 
_ e x i t 并不执行标准I / O 缓存的刷新操作。 
如果用e x i t 而不是_ e x i t ,它刷新开关闭了所有标准I / O 流,这包括标准输出。 
虽然这是由子进程执行的,但却是在父进程的地址空间中进行的,所以所有受到影响的标准I/O FILE 对象都是在父进程中的。
6. 什么是“zombie”进程?在我们的程序中如何防止“zombie”进程?(试说出其中的三种方法) 
一个已经终止、但是其父进程尚未对其进行善后处理(获取终止子进程的有关信息、释放它仍占用的资源)的进程被称为僵死进程(z o m b i e )。 
避免z o m b i e 的方法: 
(1)在S V R 4 中,如果调用s i g n a l 或s i g s e t 将S I G C H L D 的配置设置为忽略,则不会产生僵死子进程。另外,使用S V R 4 版的s i g a c t i o n ,则可设置S A _ N O C L D WA I T 标 
志(见表1 0 - 5 )以避免子进程僵死。(10.7) 
(2)调用f o r k两次。程序8 - 5 实现了这一点。 
(3)用waitpid等待子进程返回.  
7. 以下代码是不可靠信号处理的经典例子之一,试说明其中的问题(包括细节): 


8. 在信号(Signal)处理中,我们必须注意两个重要的问题:可重启动的系统调用和可重入函数。试说明以下两个问题: 
a) 在Solaris中如何设置可重启动的系统调用标志(提示:使用sigaction)。 
b) 什么是异步事件安全(Asyn-signal safe)函数?举例说明异步事件不安全的函数(即一般在信号处理程序中不能调用的函数)。(例外,提醒大家:在信号处理程序中注意保存errono)。  

9. 在使用Pthread时,典型的代码如下: 
pthread_attr_init( &attr );/* initialize attr with default attributes */ 
pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM ); 
pthread_create( &tid, &attr, start_func, arg ); 
说明以上代码中的PTHREAD_SCOPE_SYSTEM所代表的含义。 

10. 在Solaris中,用于线程间同步的机制主要包括:POSIX互斥锁(Mutex Lock)、POSIX读写锁(read-write lock)、POSIX信号量(semaphore)和POSIX条件变量(condition variable)。试简要说明以上几种同步机制的主要用途和区别。  

11. 在Solaris中,POSIX互斥锁主要用于线程间同步。说明POSIX互斥锁用于进程间同步时的主要步骤。(提示:使用系统调用mmap and ftruncate, 注意cleanup)。 
◆ 互斥锁 

互斥锁(mutex)使得某一确定时刻只有一个线程可以访问保护中的数据。 

◆ 读/写锁 

采用读写锁,允许多个线程同时读访问共享数据区,但是只能有一个线程写访问 
共享数据区。 

绝大多数设备驱动程序不使用读写锁。这种锁比互斥锁慢,仅当经常出现多个线 
程需要同时读访问共享数据而同时较少有写访问时,才采用读写锁,互斥锁此时可能 
导致写访问延迟。参看rwlock(9F)了解更多信息。 

◆ 信号灯 

信号灯也是设备驱动程序编写中一种可选的线程同步机制,参看semaphore(9F) 
了解更多细节。 

◆ 线程同步 

除了需要保护共享数据区外,驱动程序经常需要保持多线程同步执行。 

◆ 条件变量 

条件变量是线程同步的标准形式,与互斥锁配合使用。互斥锁用于确保检查条件 
变量时是原子的,如果被检查的条件变量无变化则线程阻塞,等待条件变量变化信号 
的唤醒。必须调用cv_init(9F)初始化条件变量,调用cv_destroy(9F)摧毁条件变量。 

注意:条件变量例程类似SunOS 4.1中的sleep()和wakeup()例程。 
代码举例 使用互斥锁和条件变量 

-------------------------------------------------------------------------- 
static int xxread ( dev_t dev, struct uio * uiop, cred_t * credp ) 
{ 
struct xxstate * xsp; 
... 

mutex_enter( &xsp->mu ); 
while ( xsp->busy ) 
{ 
cv_wait( &xsp->cv, &xsp->mu ); 
} 
xsp->busy = 1; 
mutex_exit( &xsp->mu ); 
perform the data access 
} /* end of xxread */ 

static u_int xxintr ( caddr_t arg ) 
{ 
struct xxstate * xsp = ( struct xxstate * )arg; 

mutex_enter( &xsp->mu ); 
xsp->busy = 0; 
cv_broadcast( &xsp->cv ); 
mutex_exit( &xsp->mu ); 
} /* end of xxintr */ 
-------------------------------------------------------------------------- 
12. 编写一个小程序,输入参数为一个文件名,它的功能描述如下: 
a) 测试此文件是否为符号连接;如果不是,则打印错误信息后退出; 
b) 读出此符号连接所指目标文件的文件名; 
c) 测试此符号连接所指目标文件是否存在于文件系统中。 
(提示:使用lstat, readlink)。 

13. 说明基于TCP协议的服务器和客户端的主要步骤,重点阐明服务器和客户端的配合关系。(提示:可以使用时序图标明配合关系)。 

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?