选择
1.linux 中把分区和目录对应的过程叫做( )。 挂载
2.信号是在软件层次上对()机制的一种模拟, 是一种异步通信方式。
中断
3.用 GCC 编译过程可以被细分为四个阶段:( )
> 预处理,编译,汇编,连接
4.编译有线程的文件要加( )参数。
-lpthread
5.父进程等待子进程的结束,可以使用的函数是( )和( )。
wait( ) waitpid( )
6.linux 主要有两个信号安装函数,分别是
signal( ) , sigaction( )
7.Linux 操作系统内核由( )编写完成。
C 和汇编
8.目录( )下存放 linux 操作系统启动时所要用到的程序
/boot
9.Linux 中采用“一对一”的线程机制,也就是一个用户线程对应一个( )。 内核线程
10.vim 三种模式:在命令模式下按下( )就进入了底线命令模式。
:
11.linux 文件系统由四部分组成,( )用于存放文件的控制信息。
超级块
12.线程本身调用( )函数可以退出线程。
> pthread_exit()
13.向消息队列发送消息的函数是( )。
msgrcv()
14.( )系统调用可以根据文件描述符来操作文件特性。
stat()
15.Valgrind 包括很多工具,( )是 valgrind 应用最广泛的工具,一个重量级的内存检查器,能 够发现开发中绝大多数内存错误使用情况,( )是主要用来检查程序中缓存使用出现的问题。
Memcheck,Cachegrind
16.信号发送函数中,( )用于设置定时器,当计时时间到达时,向进程发送 SIGALRM 信号。
setitimer()
加粗样式17.当一个线程的属性设置为( ),该线程结束时立即释放它所占有的系统资源。
分离状态
18.以下哪种方式属于异常终止一个进程(D)
D.接到一个信号并终止。
19.下列命令哪个是创建线程私有数据命令(A)
A.pthread_key_create()
20.下面哪种通信方式适用于不同机器之间的进程通信。
(D ) 套接字
21.创建或打开消息队列的函数为(A )
msgget()
22.linux 中通过调用 waitpid()函数得到进程的退出信息,该函数原型为 pid_t waitpid(pit_t pid, int *statloc, int options);当第一个参数 pid 取值为-1 时,表示(A) A 等待任一子进程退出,相当于
wait()。
23.Linux 环境中使用 kill 函数向进程或进程组发送信号。Kill 函数原型为 int kill(pid_t pid, int signo);当第一个参数 pid>0 时,表示( A )
A 发送信号给进程 ID 为 pid 的进程;
24.共享主存基本操作( A )将共享主存区映射到进程虚拟地址空间。
A shmat()
25.修改消息队列状态信息的命令是(B)
B msgctl()
26.使用 gdb 调试程序时,next 和 step 命令的作用?( )
> 统调用的函数原型 next:单步运行,不进入函数内部; setp:单步运行,进入函数内部
27.Linux 系统的设备文件分为三类?( )
> 字符设备文件、块设备文件和网络设备文件
28.标准 I/O 提供了三种类型的缓冲,分别是?( )
> 全缓冲,行缓冲,不带缓冲
- 一个完整的信号生命周期包含 4 个重要的事件,这 4 个重要事件分别是?( )
> 信号诞生 信号在进程中注册 信号在进程中注销 信号处理函数执行完毕
30.互斥锁只有两种状态,即?( ) 开锁和上锁
31.在标准 IO 库中,rewind 函数作用?( ) 将文件流指针指向文件起始位置
32.c 语言中没有明确给定初值的全局变量和静态变量存放在哪儿?( )
> 未初始化数据区
33.函数 geteuid()用于得到进程的?( )
> 用户有效 UID
34.一个进程是 ( )
> C、PCB 结构与程序和数据的组合。
35.一个进程调用 wait 或 waitpid 函数,可能产生 3 中情况,下列不属于这 3 种 情况的是 ( )。 、
> D、如果该进程没有子进程,立即返回,返回值为 0。
36.返回调用进程的进程标识号的系统函数是 ( )。
A、 getpid
37.程序和进程是两个不同的概念,以下不能描述这个观点的是 ( )。
B、同一个程序运行 10 次,产生的是同一个进程
38.fork 函数在父进程中的返回值是 ( )。
A、创建的子进程的进程标识号
39.在 Linux 中,下列不属于正常结束进程的方法是 ( )。
D、调用 abort 函数。
40.以下程序的输出结果是( )
******B、===================start of file
—parent my child is 4759,my pid is 4758,myparent pid is 3700
—child,my pid is 4759,my parent pid is 4758
===================end of file
===================end of file
41.以下程序输出结果是( )
C、parent, var = 288 child, var = 100
------------finish---------------
------------finish---------------******
42.以下程序输出结果是( )
**A、child, p = 7000, var = 1000 parent, p = 0, var = 100
43.哪种进程之间的通信,数据不可以重复读( ) B、fifo C、管道
44.下述是 Linux 下多线程编程常用的 pthread 库提供的函数名和意义,说法不正确的是?( )
D、pthread_exit 杀死一个线程
45.对线程函数来说,说法正确的是( ):
> A、pthread_create 中参数 arg 是传递给 start_routine 函数的参数
46.对互斥锁及条件变量说法不正确的是( ):
> D、在使用条件变量时,互斥锁会失去作用,所以是否有互斥锁关系不重要
47.以下说明正确的是( ):
> B、线程是一个独立的指令流,是在进程中被创建的,随进程的关闭而关闭
48.线程 A SendMessage 给线程 B,线程 B 处理该消息时又 SendMessage 给线程 A,会出现 ( ):
> B、继承执行
48.linux 文件系统通常由四部分组成:引导块,超级块,索引节点和( )。 B、数据块
49.任何进程在运行时默认打开的三个流对象,都有相应的文件描述符,标准文件描述符定 义标准输入设备的值为( )。 A、0
50.系统调用的函数原型 int open(const char *pathname, int flags),flag 值中( )表示以读写的 方式打开文件
。 *C、O_RDWR 51 系统调用的函数原型 int open(const char pathname, int flags),flag 值中( )表示若文件 存在且为只读或只写成功打开,则将长度截为 0。 B、O_TRUNC 52此行代码
length=lseek(fd,0,SEEK_END);中的 length 的值表示( )。
A、文件 lseek.txt 的大小
53.使用下列函数调用 int fcntl(int fd, int cmd);来实现文件描述符的复制,cmd 参数应使用哪 一个?
A、F_DUPFD
54.阅读程序填空:如果想要获取文件的大小,空白处应该填写以下哪个答案。 A、 statBuf.st_size
55.在创建文件和目录时候,有默认权限。如果 umask 值为 0022,则文件的默认权限为( ) B、0644
56.执行程序,代码输出结果为( )。 A.link num:2
57.获取目录的系统调用函数为( ) 。 B、getcwd()
填空
- gcc 编译过程:预处理、编译、汇编、连接。 Jdb:b:设置断点;r:执行程序;c:执行下面的程序 Vim:nyy:赋值 n 行;ndd:删除 n 行;p 或 P:粘贴在光标所在行的下一行或者上一 行。
- 进程初始化数据区:全局初始化数据区/静态数据区。 进程的运行环境:代码区、初始化数据区、未初始化数据区、堆区、 栈区
- 进程的堆区:用于动态内存分配。一般由程序员分配和释放,若程序员不释放,程序结 束时由 OS 回收。
- Linux 文件系统中的块有(根据块使用的不同):引导块、超级块、Inode 块、数据块。 控制信息、文件基本属性等是 Inode 节点,为文件系统索引。存放数据的为数据块。超 级块中含有文件系统的基本信息,如块大小、指向空间 inode 和数据块的指针等相关信 息。
- 进程运行时默认打开的标准对象:标准输入设备 stdin、标准输出设备 stdout、标准错误 输出设备 stderr。
- 软连接和硬链接的特点:硬链接和原来的文件公用一个 Inode 节点。相当于加了个相同 的文件,只是改了改名字。 硬链接创建函数:link 删除硬链接函数:unlink 软连接创建函数:symlink
读取软连接中的内容所用的函数:readlink(文件名,读取到的空间,读取的大小)。
- 修改文
件权限命令:chmod、chgrp、chown。
- 文件描述符为整形:对于用户空间来说,任何打开的文件都将分配一个唯一非负整数, 用于标识该打开文件,该值即文件描述符,为一个大于等于 0 的整数。
- 权限的值,读:4 写:2 执行:1 注意:前三位为用户的权限,再三位为所属组的权 限,再三位为其他用户的权限。
- 获取文件属性,是否穿透。stat 函数具有穿透能力,能够穿透链接文件;而 lstat 函数不 具有穿透能力,不穿透链接文件,文件类型还为链接文件。
- opendir 函数:打开一个目录,返回一个目录流指针。参数为欲打开目录的名称(路径)。 mkdir 函数:第一个参数时欲创建的目录文件路径,第二个参数时创建目录的权限。
- wait 函数:调用 wait 函数的父亲进程将堵塞式等待改进的任意一个子进程结束后,回收 该子进程的内核进程资源。参数用来接受子进程退出状态。返回值为子进程的 PID。 waitpid 函数,用来等待指定子进程结束。返回值为子进程的 PID。 第一个参数,大于 0 时,表示等待进程 PID 为该 PID 值的进程结束; 等于 0 时,表示等待与当前进程的进程组 PGID 一致的进程结束; 等于-1 时,与 wait 函数相同; 小于-1 时,表示等待进程组 PGID 是此值的绝对值的进程结束。 第二个参数用来接受等待进程的结束状态。第三个参数一般设置为。
- fork 函数:创建进程。
- 进程的进程块没有被释放,称为进程的僵死状态。
- Fcntl 函数:修改某个文件描述符的特殊属性
- 创建硬链接的系统调用:link()
- 安装信号处理函数:signal 和 sigaction。
- 信号的生命周期:在目的进程中安装信号;进程产生信号;信号在目的进程中被注册(目的进程收到信号); 信号在进程中被注销(在执行相应处理函数之前);信号生命终止(执行完响应处理函数后 再恢复到被中断的位置继续执行)。
- 消息队列中发送信息的函数:msgsnd
- 信号是在软件层次上对中断机制的一种模拟,是一种异步通信方式。
- 接受消息队列的函数 msgrcv
- alarm()设置定时器
- 信号分为可靠信号和不可靠信号。
- 管道分为有名管道和匿名管道。
- 互斥锁的两种状态:上锁和解锁。
- 自己退出线程的函数:pthread_exit() 被取消线程运行:pthread_cancle()
- 互斥锁、条件变量、读写锁的初始化 互斥锁的初始化:pthread_mutex_init() 条件变量的初始化:pthread_cond_init() 读写锁的初始化:pthread_rwlock_init()
- 读写锁:非阻塞的加锁解锁和阻塞的加锁解锁。 堵塞的方式申请读锁:pthread_rwlock_rdlock() 非堵塞的方式申请读锁:pthread_rwlock_tryrdlock() 堵塞方式申请写锁:pthread_rwlock_wrlock()
非堵塞方式申请写锁:pthread_rwlock_trywrlock()
- 线程编译的时候加上-lpthread。
- 回收线程的函数:pthread_join()
- 互斥锁的上锁函数是 pthread_mutex_lock(),非阻塞加 try; 解锁函数是 pthread_mutex_unlock()。
- 面向连接的编程:TCP;面向无连接的是:UDP
- 在不同主机间进行通讯的是:scoket 或者是套接字
- TCP 和 UDP 都是传输层的协议。
- 三次握手:连接建立、数据传输、连接释放。
- 创建套接字的函数 scoket()
- 网络编程的常见函数
监听网络函数:listen() 发起连接函数:connect()
接受连接函数:accept() 读写 scoket 对象:read()/write()
TCP 发送和接受数据:send()/recv() 关闭 scoket对象:close()
简答题
1.简述一下系统调用和库函数 举例说明
库函数:由系统提供,用户无须定义,也不必在程序中作类型说明,只需在程序前包含有该函数 原型的头文件即可在程序中直接调用 如使用 printf
return 系统调用:操作系统的一部分;用户应用程序访问并使用内核所提供的各种服务的途径即是系 统调用。如 exit
2.open 系统调用的打开标志 只读:O_RDONLY 只写:O_WRONLY 读写:O_RDWR 写入时添加至文件末尾:O_APPEND 不存在时创建:O_CREAT 截断文件为零长度:O_TRUNC
- vfs 虚拟文件系统 虚拟文件系统(Virtual File System, 简称 VFS), 是 Linux 内核中的一个软件层,用于给用 户空间的程序提供文件系统接口;同时,它也提供了内核中的一个 抽象功能,允许不同的 文件系统共存。系统中所有的文件系统不但依赖 VFS 共存,而且也依靠 VFS 协同工作。
- VFS 是什么 VFS 的作用就是采用标准的 Unix 系统调用读写位于不同物理介质上的不同文件系统,即 为 各类文件系统提供了一个统一的操作界面和应用编程接口。VFS 是一个可以让 open()、read()、
write()等系统调用不用关心底层的存储介质和文件系统类型就可以工作的粘合层。
- linux 文件类型 普通文件、目录文件、管道文件、字符设备文件、软链接文件、块文件、套接字文件
- 什么是进程,进程资源由哪两个组成 进程是计算机中程序的一次数据集合运算的活动,是系统进行调度和分配的基本单元,是操 作系统的基础 进程资源由内核空间进程资源 用户空间进程资源
- 进程结构 一个正在运行着的进程在内存空间中申请的代码区、初始化数据区、未初始化数据区、堆区、 栈区 5 个部分。
- 程序与进程的区别 动态和静态的区别:进程是程序及其数据在计算机上的一次运行活动,是一个动态的概念, 而程序是一组有序的指令集和,是一种静态的概念 生命周期的区别:进程是程序的一次执行过程,他是动态创建和消亡的,程序是一组代码的
集合,他是永久存在的 组成的区别:进程由程序 数据和 PCB 三部分组成,程序是一组有序的集合指令
9.fork 返回值的意义 如果执行成功,在父进程中将返回子进程的 PID,类型为 pid_t,子进程将返回 0,以区别父 子进程。 如果执行失败,则在父进程中返回-1,错误原因存储在 errno 中。
10.return 和 exit 的区别: return 是语言级别的,它表示了调用堆栈的返回;而 exit 是系统调用级别的,它表示一个进 程的结束。 在 main 函数里,return(0)和 exit(0)是一样的,子函数用 return 返回,而子进程用 exit 退出,
调用 exit 时要调用一段终止处理程序,然后关闭所有 I/O 流
- 什么是孤儿进程 谁负责回收孤儿进程 孤儿进程就是其在正常运行时,父进程已经结束,导致其内核资源无法被父进程回收,孤儿 进程在父进程结束时将会把父进程设置为 init 进程,init 会对孤儿进程的资源进行回收处理
12.僵尸进程是什么,谁消灭 僵尸进程:进程已经退出,但它的父亲进程还没有回收内核资源的进程,即该进程在内核空 间的 PCB 没有释放。利用 kill 函数杀死父进程,僵尸进程会变成孤儿进程被 init 进程收养。
- fork 和 vfork 的区别与联系 区别: fork()用于创建一个新进程。由 fork()创建的子进程是父进程的副本。即子进程获取 父进程 数据空间,堆和 栈的副本。父子进程之间不共享这些存储空间的部分。而
vfork()创建的进 程并不将父进程的地址空间完全复制到子进程中,因为子进程会立即调用 exec (或 exit)
于是也就不会存放该地址空间。相反,在子进程调用 exec 或 exit 之前,它在父 进程的 空间进行。 vfork()与
fork()另一个区别就是:vfork 保证子进程先运行,在它调用 exec 或 exit 之 后 父进程才可能被调度运行。 相同:
两者被调用一次,但是返回两次。两次返回的唯一区别是子进程的返回值是 0,而 父进程 的返回值则是新子进程的进程 ID。
14.父进程调用 wait 能出现的三种情况 当子进程都在执行时,wait 会使父进程进入阻塞状态 当恰好有子进程结束时,wait 会回收子进程资源并且获得子进程结束状态 当无子进程时 wait 会立刻返回-1 并且显示报错信息
15.简述可靠信号和不可靠信号的处理过程: 如果进程在屏蔽某个信号的时间内,其他进程多次向其发送同一个信号,不可靠信号只有一 次未决记录,当进程解除屏蔽后,该信号只会被捕捉一次;而可靠信号操作系统会记录所有 的发送,当进程解除屏蔽后,操作系统会捕捉对等次数。
16.简单介绍一下信号的定义及其分类。 信号是表示消息的物理量,是运载消息的工具 信号是软件中断,是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信 号与处理器收到一个中断请求可以说是一样的
分类:确定信号和随机信号;连续信号和离散信;周期信号和非周期信号;能量信号与功率 信号;因果信号与反因果信号;实信号与复信号
17.进程间通信方式: 信号,匿名管道,命名管道,信号量,共享内存,消息队列,套接字,Socket
- 请解释一下有名管道和匿名管道的区别? 匿名管道是由 pipe 函数创建 并打开的 命名管道是由 mkfifo 函数创建 的 ,打开用 open 命名管道和匿名管道唯一的区别就是在创建的打开,一旦这些工作完成后,它们有相同的意 义
19.简单介绍一下匿名管道及其特点 匿名管道是半双工的,只有一个写端和一个读端 匿名管道不是普通的文件,不是在磁盘上,而是在内存中的,所以它的生命周期随进程的结 束而结束 匿名管道是基于字节流来通信的
其本身有同步互斥的效果 匿名管道只能使用于有血缘关系的进程之间的通信
20.Please describe the difference of signal() and sigaction() in brief(描述一下 signal 和 sigaction 的区别与联系英文题) 不同点:signal
只能调用信号处理函数,但是无妨向其输入附带的数据 sigaction 可以向信号处理函数传递信息,并且可以设置信号掩码,返回设置之前的
sigaction 相同点:都可以为信号设置信号处理函数 共用了同一个内核函数 do_sigaction
21.信号处理方式 忽略此信号。 自定义捕捉信号函数。 执行系统默认操作。
- 信号产生的方式 当用户按某些键时产生信号。 硬件异常产生信号。 终止进程信号。 软件异常产生信号
23.信号的生命周期 在目的进程中安装信号;进程产生信号;信号在目的进程中被注册(目的进程收到信号); 信号在进程中被注销(在执行相应处理函数之前);信号生命终止(执行完响应处理函数后 再恢复到被中断的位置继续执行)。
24.简述什么是线程及特点 线程就是系统运算执行的最小单位,其所占资源较少 线程是进程的一个执行序列 线程可以看作是轻量化的进程,线程之间的切换代价小
25.pthread_kill 函数和 pthread_cancle 函数的区别:(两个都是终止进程的)pthread_kill 函数的功能是向指定线程发送信号,信号为 0 时用于检查此线程 ID 的线程 是 否存活。pthread_cancel
函数的功能是给线程发送取消信号,使线程从取消点退出。
- pthread_exit()和 pthread_cancel()的区别 pthread_exit()是结束本线程 pthread_cancel()是结束其他线程
- 简述互斥锁与读写锁的区别与联系。 区别:读写锁区分读者和写者,而互斥锁不区分 互斥锁同一时间只允许一个线程访问该对象,无论读写;读写锁同一时间内只允许一个写者, 但是允许多个读者同时读对象。
联系:读写锁在获取写锁的时候机制类似于互斥锁。
28.条件变量中 pthread_cond_wait 实现的步骤 解锁 判断条件是否成立 如果成立则上锁执行,不成立将进入阻塞状态
- 线程与进程的区别 进程是资源分配的最小单位,线程是程序执行的最小单位。 进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段。而线程是共享进程中的数据的,使用相同的地址 空 间,因此 CPU
切换一个线程的花费远比进程要小很多,同时创建一个线程的开销也 比 进程要小很多。
线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据,而进程 之 间的通信需要以通信的方式进行。
多进程程序更健壮,多线程程序只要有一个线程死掉,整个进程也死掉了,而一个进 程死掉并不会对另外一个进程造成影响,因为进程有自己独立的地址空间。
- tcp 和 udp 的区别 TCP 需要连接,UDP 是无连接的,发送数据之前不需要建立连接 TCP 提供可靠的服务,通过 TCP 连接传送的数据,无差错,不丢失 TCP 逻辑通信信道是全双工的可靠信道,UDP 则是不可靠信道
- TCP 的三次握手 第一次握手 客户主动(active open)去 connect 服务器,并且发送 SYN 假设序列号为 J, 服务器是被动打开(passive open) 第二次握手 服务器在收到 SYN 后,它会发送一个 SYN 以及一个 ACK(应答)给客户,ACK 的序列号是 J+1 表示是给 SYN J 的应答,新发送的 SYN K 序列号是 K 第三次握手 客户在收到新 SYN K, ACK
J+1 后,也回应 ACK K+1 以表示收到了, 然后两边就可以开始数据发送数据了
- osi 七层模型 应用层 表示层 会话层 传输层 网络层 数据链路层 物理层
33.使用 gdb 调试程序时,next 和 step 命令的作用? next:单步运行,不进入函数内部; setp:单步运行,进入函数内部
34.Linux 系统的设备文件分为三类? 字符设备文件、块设备文件和网络设备文件
35.标准 I/O 提供了三种类型的缓冲,分别是? 全缓冲,行缓冲,不带缓冲
- 一个完整的信号生命周期包含 4 个重要的事件,这 4 个重要事件分别是? 信号诞生 信号在进程中注册 信号在进程中注销 信号处理函数执行完毕
37.互斥锁只有两种状态,即? 开锁和上锁
38.在标准 IO 库中,rewind 函数作用? 将文件流指针指向文件起始位置
39.c 语言中没有明确给定初值的全局变量和静态变量存放在哪儿? 未初始化数据区
40.函数 geteuid()用于得到进程的? 用户有效 UID
编程题
1.创建文件 file1,写入字符串“abcdefghijklmn”; 创建文件 file2,写入字符串“ABCDEFGHIJKLMN”; 读取file1中的内容,写入file2,使file2中的字符串内容为“abcdefghijklmn ABCDEFGHIJKLMN”
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
int main()
{
int fd1,fd2;
char str[14];
fd1 = open("file1",O_RDWR|O_CREAT,S_IRWXU);
if(fd1 < 0)
perror("open");
write(fd1,"abcdefghijklmn",14);
lseek(fd1,0,SEEK_SET);
fd2 = open("file2",O_RDWR|O_CREAT,S_IRWXU);
if(fd2 < 0)
perror("open");
lseek(fd2,14,SEEK_END);
write(fd2,"ABCDEFGHIJKLMN",14);
read(fd1,str,14);
lseek(fd2,0,SEEK_SET);
write(fd2,str,14);
close(fd1);
close(fd2);
system("cat file2");
printf("\n");
return 0; }
2.创建新文件,该文件具有用户读写权限。 采用 dup/dup2/fcntl 复制一个新的文件描述符,通过新文件描述符向文件写入“class_name” 字符串;通过原有的文件描述符读取文件中的内容,并且打印显示
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
int fd,fd1;
char *str = "class_name";
fd = open("file",O_CREAT|O_RDWR);
if(fd < 0)
perror("open");
fd1 = dup(fd);
if(fd1 < 0)
perror("dup");
write(fd1,str,strlen(str));
lseek(fd,0,SEEK_SET);
char buf[12];
read(fd,buf,12);
printf("The buf is:%s\n",buf);
close(fd);
close(fd1);
return 0; }
3.递归遍历/home 目录,打印出所有文件和子目录名称及节点号。 判断文件类型,如果是子目录,继续进行递归遍历,直到遍历完所有子目录为止。
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
void show(char *path)
{
DIR *dir;
char str[128];
struct dirent *dirp;
struct stat statbuf;
dir = opendir(path);
if(dir)
{
while((dirp = readdir(dir)) != NULL) {
sprintf(str,"%s/%s",path,dirp->d_name);
if(lstat(str,&statbuf) < 0)
perror("lstat");
if(dirp->d_name[0] == '.')
continue;
if(S_ISDIR(statbuf.st_mode))
{
show(str);
printf("The dirent's name is: %s\n",dirp->d_name);
printf("The dirent's inode is: %d\n",dirp->d_ino);
}
else
{
printf("The file's name is: %s\n",dirp->d_name);
printf("The file's inode is: %d\n",dirp->d_ino);
} } }
else
perror("opendir");
closedir(dir);
}
int main()
{
show("/home");
return 0; }
4.打印字符串“hello world!” 在打印字符串“hello world!”前调用三次 fork,分析打印结果。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
fork();
fork();
fork();
printf("hello world!!!\n");
return 0 }
5.创建子进程 在子进程中打开文件 file1,写入自己的“班级_姓名_学号”, 父进程读取 file1 中的内容,并且打印显示。 在父进程中获取已经结束的子进程的状态信息,打印该信息,并且打印结束的子进程的进程 号。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
int main()
{
int fd,pid;
fd = open("file",O_CREAT|O_RDWR,S_IRWXU);
if(fd< 0)
perror("open");
pid = fork();
if(pid == 0)
{
printf("This is the child!\n");
char str[128] = "移动二班_段振威_1915925158";
if(write(fd,str,128) < 0)
perror("write");
exit(5);
}
else
{
printf("This is the father!\n");
char buf[128];
int n,status;
if(read(fd,buf,128) < 0)
perror("read");
printf("The buf is: %s\n",buf);
if(wait(&status) < 0)
perror("perror");
if(WIFEXITED(status))
n = WEXITSTATUS(status);
else
printf("wait error!\n");
printf("The child's pid is: %d\n",pid);
printf("The child exit status is: %d\n",n);
}
return 0;
}
6.在父进程中定义变量 n,在子进程中对变量 n 进行++操作;并且打印变量 n 的值,打印子 进程 pid; 在父进程中打印变量 n 的值,并且打印父进程 pid。 要求分别用 fork 和 vfork 创建子进程。
//------fork
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
int main()
{
int n = 1;
if(fork() == 0)
{
printf("This is child,the pid is%d\n",getpid());
printf("The n is: %d\n",++n);
}
else
{
printf("This is father,the pid is%d\n",getpid());
printf("The n is: %d\n",n);
}
return 0;
}//-----vfork
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int n = 1;
pid_t pid;
pid = vfork();
if(pid < 0)
perror("vfork");
else if(pid == 0)
{
printf("This is child,the child's pid is: %d\n",getpid());
printf("The n is: %d\n",++n);
exit(0);
}
else
{
printf("This is father,the father's pid is: %d\n",getpid());
printf("The n is: %d\n",n);
}
return 0;
}
7.利用匿名管道实现父子进程间通信,要求 父进程发送字符串“hello child”给子进程; 子进程收到父进程发送的数据后,给父进程回复“hello farther”; 父子进程通信完毕,父进程依次打印子进程的退出状态以及子进程的
pid。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main()
{
int fd1[2],fd2[2];
pipe(fd1);
pipe(fd2);
int pid;
pid = fork();
if(pid < 0)
perror("fork");
else if(pid == 0)
{
close(fd1[0]);
close(fd2[1]);
char str[12];
printf("This is the child!\n");
if(read(fd2[0],str,12) > 0)
{
printf("Received the news: %s\n",str);
if(write(fd1[1],"hello father",12) < 0)
perror("write");
}
else
perror("read");
exit(5);
}
else
{
int status;
printf("This is the father!\n");
close(fd1[1]);
close(fd2[0]);
char buf[24] = "hello child";
if(write(fd2[1],buf,12) < 0)
perror("write");
else
{
printf("Send news successful!\n");
}
wait(&status);
if(WIFEXITED(status))
{
printf("The child's pid is: %d\n",pid);
printf("The child's exited status is: %d\n",WEXITSTATUS(status));
} }
return 0;
}
- 利用匿名管道实现兄弟进程间通信,要求 兄进程发送字符串“This is elder brother ,pid is (兄进程进程号)”给第进程; 第进程收到兄进程发送的数据后,给兄进程回复“This is younger brother ,pid
is(第进程进 程号)”;
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
int main()
{
int fd1[2],fd2[2];
pipe(fd1);
pipe(fd2);
int pid;
pid = fork();
if(pid == 0)
{
printf("This is the elder brother!\n");
printf("The elder's father's pid is: %d\n",getppid());
close(fd1[1]);
close(fd2[0]);
char str1[64],str2[64];
sprintf(str1,"This is the elder brother,pid is %d",getpid());
if(write(fd2[1],str1,64) < 0)
perror("write");
if(read(fd1[0],str2,64) < 0)
perror("read");
else
printf("The news from younger is: %s\n",str2);
}
else
{
if(fork() == 0)
{
printf("This is the younger brother!\n");
printf("The younger's father's pid is: %d\n",getppid());
close(fd1[0]);
close(fd2[1]);
char buf1[64],buf2[64];
if(read(fd2[0],buf1,64) > 0)
{
printf("The news form elder is: %s\n",buf1);
sprintf(buf2,"This is the younger brother,pid is %d",getpid());
if(write(fd1[1],buf2,64) < 0)
perror("write");
}
else
perror("read");
} } }
- 利用有名管道文件实现进程间通信,要求 写进程向有名管道文件写入 10 次“hello world”; 读进程读取有名管道文件中的内容,并依次打印
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
int main()
{
int pid,fd;
if(mkfifo("fifotest",0666) < 0)
perror("mkfifo");
pid = fork();
if(pid < 0)
perror("fork");
else if(pid == 0)
{
printf("This is the write process!\n");
int fd = open("fifotest",0666);
for(int i = 0; i < 10;i++)
{
if(write(fd,"hello world",12) < 0)
perror("write");
sleep(1);
}
close(fd);
}
else
{
char str[128];
printf("This is the read process!\n");
int fd1 = open("fifotest",0666);
for(int i = 0;i < 10;i++)
{
if(read(fd1,str,128) < 0)
perror("read");
else
printf("%s\n",str);
}
system("rm -f fifotest");
} }