5.1
1.编写一个调用 fork()的程序。谁调用 fork()之前,让主进程访问一个变量(例如 x) 并将其值设置为某个值(例如 100)。子进程中的变量有什么值?当子进程和父进程都改变 x 的值时,变量会发生什么?
答:根据终端的输出结果我们可以看到一共有两个命令提示符出现,说明确实是运行了两个进程。父进程子进程首先就分别输出本进程中x的值,随后进行不同的修改。可以看到先执行的是父进程输出x初始值,再输出了父进程的改变的x的值。随后执行的子进程输出的又是x初始值,不是父进程改变后的x值,最后输出子进程改变的x值。可以得知一个变量是不会跨进程实现的,虽然有着相同的命名,但是它们仍然独立于各自的进程不会被其他进程的指令干扰。
5.2
2.编写一个打开文件的程序(使用open()系统调用),然后调用 fork()创建一个新进程。子进程和父进程都可以访问open()返回的文件描述符吗?当它我并发(即同时)写入文件时,会发生什么?
答:在我编写的代码中由tmp局部变量获取打开的文件5.2.txt的文件描述符。因为文件描述符是一个非负整数,所以tmp的初值我赋予-1。同时在父子进程中分别tmp = open(“./5.2.txt,O_WRONLY | O_CREAT”); 来获取5.2.txt文件的文件描述符,因为open()的返回值就是打开文件的文件描述符。由输出截图我们可以看到“father get the data 4”和“child get the data 4”,其中4就是5.2.txt的文件描述符,所以父子进程都可以访问open()返回的文件描述符(提示:有些人可能会认为tmp只是在fork()函数调用前进行了初始化-1,那么有没有可能第二个进程tmp因为open()获取5.2.txt文件描述符失败而没有更新,于是也为4呢?其实变量是不会跨进程实现的,两个进程的tmp不是同一个,父子进程刚运行时tmp的初值都会是-1,经过手动添加tmp = -1到父子进程代码中验证与目前结果一致)。最后也可以看到当父子进程并发写入文件时outfile << “From the father.\n”;和outfile << “From the child.\n”;都成功写入,打开5.2.txt文件确实都写入其中。
5.4
4.编写一个调用 fork()的程序,然后调用某种形式的 exec()来运行程序/bin/ls。看看是否可以尝试 exec()的所有变体,包括 execl()、execle()、execlp()、execv()、execvp()和 execvP()。
为什么同样的基本调用会有这么多变种?
答:由上图可知所有的exec变体都可以运行程序/bin/ls。其实execve()是基础的系统调用,其他的变种都是在这个基础上包装的库函数。因为要应对各种不同的需求,所以才衍生出了这么多的形式。比如“l”表示参数以列表的形式表示,“v”表示参数以数组的形式表示,“p”表示在PATH中搜索执行文件,“e”表示可附加环境参数。