标签:
【学习时间:8小时】 【学习内容:教材第十章 之 I/O总结;实验楼私有课程《深入理解计算机系统》 之 系统级I/O】
【重定向其实是unix系统优越性的一种体现(与管道相似);将一种操作的结果重定向到另外一种操作上,这样的思想保证了“专务专用”,将单个操作做到极致,又为用户自己提供了完善功能的平台(比如重定向,比如管道)。】 - unix外壳提供了I/O重定向操作符,允许用户将磁盘文件和标准输入输出连接起来。例如:
ls > foo.txt;
使得外壳加载和执行ls程序,将标准输出重定向到foo.txt。
工作方式:
#include <unistd.h>
int dup2(int oldfd,int newfd);
拷贝描述符表项oldfd到描述符表项newfd,同时覆盖掉newfd之前的内容。如果newfd已经打开,就先关闭newfd再进行操作。
前提:假设描述符1(标准输出)对应于文件A,4对应于文件B,A和B的引用计数等于1.
过程:两个描述符都指向文件B,文件A已经被关闭,它之前对应的文件表和v-node也已经被删 除;文件B的引用计数增加,之后的任何标准输出(描述符1)的数据都被重定向到文件B。
【之前的输入输出函数并没有特定性,而是适用于通常情况下的I/O;标准I/O库针对I/O的具体情况,分类给出了特定的I/O函数;从一定角度而言,是“高级”的I/O函数。另外,与此相关的“流”的概念是和指针很相似的,也是一种“抽象”。】
【C语言编程的时候,经常会因为输入域输出交叉调用导致输入或者输出函数不能取到想要的值】
unix风格:例如fork函数和外套函数,返回值既包括错误代码,又包括有用的结果。
if((pid = wait(NULL))<0)
{
fprintf(stderr,"wait error:%s\n",strerror(errno));//将errno设置为指向错误原因的代码
exit(0);
}
错误处理包装函数
unix风格
pid_t Wait(int *status)
{
pid_t pid;
if(pid = wait(status)<0)
unix_error("wait error");
return pid;
}
Posix风格
void Pthread_detach(pthread_t tid)
{
int rc;
if(rc=pthread_detach(tid) != 0)
posix_error(rc,"Pthread_detach error");
}
DNS风格
struct hostent *Gethostbyname(const char *name)
{
struct hostname *p;
if((p = gethostbyname(name)) == NULL)
dns_error("Gethostbyname error");
return p;
}
【参考上面的函数,标准输入的描述符为0,则使用:
int dup2(5,0);
进行重定向。】
#include "csapp.h"
int main()
{
int fd1,fd2;
char c;
fd1 = Open("foobar.txt",O_RDONLY,0);
fd2 = Open("foobar.txt",0_RDONLY,0);
Read(fd2,&c,1);
Dup(fd2,fd1);
Read(fd1,&c,1);
printf("c= %c\n",c);
exit(0);
}
【fd1被重定向到了fd2,所以输出的是第二个字母(之前的第一个字母‘f’已经被读过了):‘o’】
【当父进程打开子进程之后,父子进程并发执行,而且,二者结束的先后顺序是不可控制的;最后,当子进程被打开之后,父子进程之后的部分是一样的;而且,最后的结果先后无法区分】
1.开始运行练习题10.1的代码时,编译出错,显示是因为无法找到“csapp.h”文件
#include "csapp.h"
int main()
{
int fd1,fd2;
fd1=Open("foo.txt",O_RDONLY,0);
Close(fd1);
fd2=Open("baz.txt",O_RDONLY,0);
printf("fd2=%d\n",fd2);
exit(0);
}
通过网上搜索,发现一篇博客给出了解答:
这一周老师给布置了一个有关IO的Open函数的实验,叫我们自己到linux上去运行一下,结果在csapp.h这个头文件上纠结了好久,在这里特别总结一下,留个纪念. 是csapp.h其实就是一堆头文件的打包,在http://csapp.cs.cmu.edu/public/code.html 这里可以下载。这是《深入理解计算机系统》配套网站,但有个疑问是csapp.h这个 是作者写的?还是出自unix的源代码了?但毫无疑问他给我们写一些程序的编写带来了方便,有了它我们就没必要在写那么多头文件了,一个就搞定。至于出处的话,就不纠结了,会用就行。
在linux下要怎么使用头文件了,linux应该没有自带csapp.h,所以要自己导入,我用的是fedora的,要放到 /usr/include的文件夹里面。打开后这里面有好多头文件... (ubuntu下是/usr/lib,其他版本的linux应该也是在usr的目录下吧)。另外还有一点,要在头文件的#end if前面加上一句#include <csapp.c>,因为那个头文件要把csapp.c文件包含进去 这样的话就可以用了。
还有就是因为csapp.c中有关于线程的头文件,在用gcc的时候最后要加上-lpthread 如 # gcc -o Ex Ex.c -lpthread
【也就是无法通过“复制”——“粘贴”完成csapp.h的添加】
【经过小组提问,发现可以通过命令行终端的mv命令进行操作】
【结果失败】
本次学习是对之前学习的精细化过程;因为知识性的新内容不多,所以我就把大部分精力放在了实践上。对于课本上的代码,尽量去打出来运行;对于之前想尝试但一直没有尝试的linux命令或者功能学习,尽力去练习。看似抓住的不多,然而不断的尝试和失败再到成功,也是很有教育意义的。
标签:
原文地址:http://www.cnblogs.com/lwr-/p/4957295.html