大多数Unix文件IO只需用到5个函数:open read write lseek close ,通常被称为不带缓存的IO,不是标准库的一部分,而是POSIX.1的一部分;POSIX= planted operate system interface x
对内核而言,打开文件都由文件描述符引用;0 对应标准输入,1对应标准输出,2对应标准出错输出;
幻数->magic number ,含义为当一个普通字符含有特殊意义时就叫幻数;
0->STDIN_FILENO 1->STDOUT_FILENO 2->STDERR_FILENO 这些都定义在文件中;
open函数:
#include
#include
#include
int open(const char *pathname, int oflag, .../*mode_t mode */);
调用成功返回文件描述符,出错为-1;
pathname是要打开或创建的文件名;
oflag参数有一系列常数值可供选择,这些常数定义在头文件中,可以同时选多个按位或"|"起来;
必选项:
O_RDONLY O_WRONLY O_RDWR 三者之一
可选项:
O_APPEND 追加到末尾;
O_CREAT 若不存在则创建,此时必须提供第三个参数mode;
O_EXCL O_TRUNC O_NONBLOCK 等
mode参数: 与O_CREAT配合使用;
S_IR USR GRP OTH 用法: S_IRUSR | S_IWUSR
S_IW USR GRP OTH 用法: S_IREAD | S_IWRITE
S_IX USR GRP OTH
#include
int close( int filedes); 成功返回0,否则-1; 当一进程终止时,它所有打开的文件都由内核自动关闭;
#include
#include
off_t lseek(int filedes, off_t offset, int whence); 成功返回新的偏移量,出错返回-1;
whence参数:
SEEK_SET 设置偏移量距文件开头offset字节;
SEEK_CUR 距当前位置加offset, 可正可负;
SEEK_END 文件长度加offset, 可正可负;文件偏移量可以大于文件长度,文件中形成空洞,读出来是0,但不占空间;
#include
ssize_t read(int filedes, void *buff, size_t nbytes); 返回值是读到的字节数; 到末尾返回0; 出错返回-1;
#include
ssize_t write(int filedes, const void *buff, size_t nbytes); 返回写入的字节数,错误返回-1;
常见的错误的原因为: 磁盘已满,超过对一个给定进程的文件长度限制;
在PCB的进程表项中有份文件描述符表, 包含一套文件描述符标志,如close-on-exec标志;包含一个指向文件表项,的指针(linux中为File object);
内核为所有打开文件维持一张文件表(linux的File object对象):包含文件状态标志,读写增写等;包含当前的读写偏移量;包含一个指向v-node的表项的指针(linux中为inode object);
每个打开的文件(设备)都有一个v-node(linux中为inode object),包含了文件类型和对此文件进行各种操作的函数指针;
linux在File object和inode object之间还有一层dentry cache,用于处理一个文件多个文件名(硬连接)的情况.
复制一个现存的文件描述符,使2个文件描述符指向同一个文件表项;
#include < unistd.h>
int dup( int filedes); 成功返回当前可用的最小的新描述符,出错返回-1;
int dup2(int filedes, int filedes2); 其中filedes是现存的描述符,filedes2是指定的新的描述符,若已经打开,就先关闭再操作,若本已经相同则不关闭;
? 又dup或dup2函数返回的新描述符的close-on-exec标志总是被清除;
ioctl函数是IO的杂物箱,用于向文件(设备)发命令,控制信息;对应的头文件是.
一些例程:
/* char_read.c */
#include
#include
#include
#include
int main()
{
char c;
int in, out;
in = open("file.in", O_RDONLY);
out = open("file.out", O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
while (read(in, &c, 1) == 1)
write (out, &c, 1);
exit(0);
}
/*copy_stdio.c*/
#include
#include
int main()
{
int c;
FILE *in, *out;
in = fopen("file.in", "r");
out = fopen("file.out", "w");
while ((c = fgetc(in)) != EOF)
fputc(c, out);
exit(0);
}
/*std_write.c*/
#include
#include
#include
int main()
{
char buffer[128] = "hello world\n";
int nread, nwrite;
nread = read(0, buffer, 128);
printf ("nread ->%d\n", nread);
if (nread == -1)
write(2, "A read error has occurred\n", 26);
nwrite = write(1, buffer, nread);
printf ("nwrite ->%d\n", nwrite);
if (nwrite != nread)
write(2, "A write error has occurred\n", 27);
exit(0);
}
/*copy_block.c*/
#include
#include
#include
#include
#include
#include
int main()
{
char block[1024];
int in, out;
int nread;
in = open("file.in", O_RDONLY);
out = open("file.out", O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
printf ("sizeof %d\t strlen %d\n", sizeof(block), strlen(block));
while ((nread = read(in, block, sizeof(block))) > 0)
write(out, block, nread);
exit(0);
}
/*dup.c*/
#include
#include
#include
#include
#include
int main(void)
{
int fd, oldstdout;
char msg[] = "this is a test\n";
fd = open("somefile", O_CREAT | O_RDWR, S_IREAD | S_IWRITE);
oldstdout = dup(STDOUT_FILENO);
dup2(fd, STDOUT_FILENO);
close(fd);
write(STDOUT_FILENO, msg, strlen(msg)); /*往文件写*/
dup2(oldstdout, STDOUT_FILENO);
write(STDOUT_FILENO, msg, strlen(msg)); /*往屏幕写*/
close(oldstdout);
return 0;
}
阅读(926) | 评论(0) | 转发(0) |