计算机系统基础(第十章)

对cs给的第十章的代码的理解,与运行结果
关于代码如何运行,大概可以用如下的方法:
先用gcc -c 命令生成文件(这里用file.c代替)以及csapp.c的.o文件然后用

gcc -o file file.o csapp.o -lpthread

因为csapp里用到了线程有关的东西,所以要加-lpthread

#include "csapp.h"
int main(int argc, char *argv[])
{
    int fd1, fd2, fd3;
    char c1, c2, c3;
    char *fname = argv[1];
    fd1 = Open(fname, O_RDONLY, 0);
    fd2 = Open(fname, O_RDONLY, 0);
    fd3 = Open(fname, O_RDONLY, 0);
    dup2(fd2, fd3);
    Read(fd1, &c1, 1);
    Read(fd2, &c2, 1);
    Read(fd3, &c3, 1);
    printf("c1 = %c, c2 = %c, c3 = %c\n", c1, c2, c3);
    Close(fd1);
    Close(fd2);
    Close(fd3);
    return 0;
}

abcde.txt文件的内容为abcde
运行./file1 abcde.txt的运行结果如下:
在这里插入图片描述
对于代码的解释,大写的Open,Read,Close仅是在csapp里进行了有关错误的处理,重新定义的函数,其他的均与原函数相同,对于类似的题可以通过画出图来处理,画出的图如下:
图一
在这里插入图片描述

图二
在这里插入图片描述

在用了三个open函数打开了同一文件三次,每次都会在文件打开表里创建一个项,且文件描述符表的项指向打开表中的表项,如第一张图,而调用dup2(fd2,fd3)后将fd2的文件打开表的表项赋给了fd3,所以fd2与fd3指向的是同一个文件打开表的表项,第一条read不必多说,在fd2读了一个字符后,光标往后移一位,因为fd3与fd2的文件打开表的表项相同,所以fd3的read会接着读,所以fd2读的是a,而fd3会接着读a后面的b所以输出的结果是c1 = a,a2 = a,c3 = b(之后不再解释类似问题,建议画图)

#include "csapp.h"
int main(int argc, char *argv[])
{
    int fd1;
    int s = getpid() & 0x1;
    printf("pid = %d,s = %d\n",getpid(),s);
    char c1, c2;
    char *fname = argv[1];
    fd1 = Open(fname, O_RDONLY, 0);
    Read(fd1, &c1, 1);
    if (fork()) {
    /* Parent */
       sleep(s);
       Read(fd1, &c2, 1);
       printf("Parent: c1 = %c, c2 = %c\n", c1, c2);
    } else {
    /* Child */
       sleep(1-s);
       Read(fd1, &c2, 1);
       printf("Child: c1 = %c, c2 = %c\n", c1, c2);
    }
    return 0;
}

我再源代码的基础上作了一些修改添加了

printf(“pid = %d,s = %d\n”,getpid(),s);

这一行,且运行如下./file2 abcde.txt,可以让结果更加的明显,运行的结果如下:
在这里插入图片描述
这里的s为进程的pid与上0x1也就是将进程的pid号最低位(二进制)赋给s,也就是说该进程(fork前)的pid号为奇数则父进程等待1s,偶数则是子进程等待1s,有关的图如下:
图一
在这里插入图片描述
图二
在这里插入图片描述

原本打开文件如图一,因此读出的字符为a,光标往后移一位,之后fork创建子进程,子进程得到了父进程所有的资源,包括打开的文件表,而后因为原进程pid为奇数,所以s为1,1-s为0,所以父进程会等待1s再执行,所以子进程接着往后读得到c2 = b,父进程等待完之后往后读c2 = c,所以有了如图的结果,有趣的是多次执行该程序并不会改变父进程子进程的执行顺序,这是因为创建了一个子进程,所以每次都是执行的两个进程,并不会改变之后执行进程的pid号,这里我们运行题1的程序再运行题2的程序,来改变奇偶性,结果如图:
在这里插入图片描述
这样就变成了父进程先运行,子进程等待1s,对于shell的提示符的解释是:提示符的输出取决于最初的父进程,也就是原进程,一旦父进程结束shell提示符就会输出,而之后运行完的子进程只能再提示符之后输出(这里为个人理解,欢迎指出错误的地方),所以子进程的结果输出在了下一个提示符之后。

#include "csapp.h"
int main(int argc, char *argv[])
{
    int fd1, fd2, fd3;
    char *fname = argv[1];
    fd1 = Open(fname, O_CREAT|O_TRUNC|O_RDWR, S_IRUSR|S_IWUSR);
    Write(fd1, "pqrs", 4); 
    fd3 = Open(fname, O_APPEND|O_WRONLY, 0);
    Write(fd3, "jklmn", 5);
    fd2 = dup(fd1);  /* Allocates new descriptor */
    Write(fd2, "wxyz", 4);
    Write(fd3, "ef", 2);
    Close(fd1);
    Close(fd2);
    Close(fd3);
    return 0;
}

这一题比较麻烦,还是把图画出来:
在这里插入图片描述

开始时这里fd1用open打开文件,带的属性的意思为如果文件不存在则创建文件并打开,存在则打开并且截断它(清空),以可读可写的方式打开,之后在空文件中写入pqrs,此时fd1的光标再s之后,而fd3是在fd1写完之后再打开的,所以打开时里面已经有pqrs存在了,而fd2的打开属性设置是O_APPEND,指的是每次写都在最后,所以fd3写了之后文件的内容为pqrsjklmn,此时fd3的光标在n之后,而之后使用dup函数将fd1的文件打开表项给fd2,所以fd2会接着fd1的光标写入wxyz,也就是在s后面写入第5~8个字符wxyz,也就是原来的jklm被覆盖了,此时文件的内容为pqrswxyzn,之后fd3接着在n后写入ef,到此时文件的内容为pqrswxyznef,所以最后输出的值为pqrswxyznef
程序运行的结果如下:
在这里插入图片描述
在这里插入图片描述

这一题说起来有点悲伤,在第一次做的时候做错了
暂时写到这,欢迎大家指正错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值