I/O

I/O?
输入/输出(I/O)是主存和外部设备(例如磁盘驱动器、终端和网络)之间复制数据的过程。 输入操作是从I/O设备复制数据到主存,而输出操作是从主存复制数据到I/O设备。

Unix I/O
一个Linux文件就是一个m字节的序列。

打开文件。应用程序要求内核打开相应的文件,一次访问I/O设备。内核返回一个很小的非负整数,叫做描述符(fd),他在后续对此文件的所有操作中标识这个文件。内核记录有关这个打开文件的所有信息。应用程序只需记住这个标识符。
shell创建的每个进程都需要打开三个文件:标准输入(fd=0)、标准输出(fd=1)、标准错误(fd=2)。
改变当前的文件位置。
读写文件。
关闭文件。
打开关闭
进程通过open函数打开一个已经存在的文件或者创建一个新文件

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int open(char *filename,int flags,mode_t mode);
//返回:成功 返回文件描述符  出错 返回-1

flags参数指明了进程访问文件的方式:

O_RDONLY:只读。
O_WRONLY:只写。
O_RDWR:可读可写。
O_CREAT:如果文件不存在,就创建它的一个截断的(空)文件。
O_TRUNC:如果文件已经存在,就截断它。
O_APPEND:在每次写操作前,设置文件位置到文件结尾处。
以上是常用的访问方式,并非全部。

mode参数指定了新文件的访问权限位:
S_IRUSR:使用者(拥有者)能够读这个文件。
S_IWUSR:使用者(拥有者)能够写这个文件。
S_IXUSR:使用者(拥有者)能够执行这个文件。
S_IRGRP:拥有者所在组的成员能够读这个文件。
S_IWGRP:拥有者所在组的成员能够写这个文件。
S_IXGRP:拥有者所在组的成员能够执行这个文件。
S_IROTH:其他者(任何者)能够读这个文件。
S_IWOTH:其他者(任何者)能够写这个文件。
S_IXOTH:其他者(任何者)能够执行这个文件。

进程通过close函数关闭一个打开的文件

#include <unistd.h>
int close(int fd);
//成功返回0 出错-1 关闭一个已经关闭的描述符会出错

读、写文件
#include <unistd.h>

ssize_t read(int fd,void *buf,size_t n);
//成功 返回读的字节数 结束为0,出错为-1

ssize_t write(int fd,sonst void *buf,size_t n);
//成功返回写的字节数  出错为-1

IO重定向
#include <unistd.h>
int dup2(int oldfd,int newfd);
//成功返回描述符,出错为-1

abcde.txt

abcde

代码1:
ffiles1.c

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;

}

因为:fd1、fd2、fd3三个文件描述符打开文件abcde.txt共享v-node表,但三个描述符指向的打开文件表不相同,分别为文件、文件2、文件3。

所以结果:

c1 = a, c2 = a, c3 = b

代码2:
ffiles2.c

int main(int argc, char *argv[])
{
int fd1;
int s = getpid() & 0x1;
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;
}

结果:

Child:c1 = a, c2 = b
Parent:c1 = a, c2 = c

代码3:
ffiles3.c

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;

}

结果:

abcde.txt

pqrswxyznef

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值