linux i o源码,Linux 文件I/O(一)之入门及练习源码

Linux 文件I/O(一)之入门及练习源码

Linux环境下,所有东西都以文件的形式存在。应用软件如果想操作一个文件,必须通过系统调用获取更高的权限。即可以直接通过系统调用操作文件如open(2),也可以通过库函数间接的使用系统调用如fopen(3)。

库函数包含了部分系统调用。一方面把系统调用抽象了,一方面方便了用户级的调用。系统调用属于内核态,库函数属于用户态。

对于文件打开来说,fopen(3)分配一个FILE结构体,其中包含该文件的文件描述符,I/O缓冲区等信息,返回这个FILE结构体的地址。对于C标准I/O库,打开的文件由FILE*指针标记,而对于内核来说打开的文件由描述符标记。

每个进程在linux内核中都有一个task_struct结构体来维护进程相关信息,称为进程描述符,每个task_struct中都有一个指针指向file_struct结构体,称为文件描述符表,其中每个表项包含一个指向已打开的文件的指针。

1.file_cpy.c 实现文件的拷贝

#include

#include

#include

#include

#include

#include

int file_cpy(int fd_src,int fd_des)

{

int sret,dret;

char str[128];

char *p;

bzero(str,128);

while((sret=read(fd_src,str,128))>0){

p=str;

while(sret){

dret=write(fd_des,p,sret);

sret=sret-dret;

p=p+dret;

}

bzero(str,128);

}

return 0;

}

int main(int argc,char *argv[])

{

int fd_src;

int fd_des;

if(argc!=3)

printf("format error\n");

fd_src=open(argv[1],O_RDONLY);

if(fd_src<0)

perror("open fd_src error");

fd_des=open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0666);

if(fd_des<0)

perror("open fd_des error\n");

file_cpy(fd_src,fd_des);

close(fd_des);

close(fd_src);

return 0;

}

此程序需注意的是当你从一个字符数组向一个文件write时,并不是你想写的都会成功写进去,这个问题可能开始不会出现,但当你写的次数足够多时就会出现问题,所以要注意把没写进去的内容再写进文件中。

2.read_block.c 终端阻塞读

#include

#include

int main(void)

{

int n;

char buf[10];

n=read(STDIN_FILENO,buf,10);

if(n<0)

perror("read");

write(STDOUT_FILENO,buf,n);

return 0;

}

3.read_noblock.c 非堵塞读

#include

#include

#include

#include

#include

#define MSG_TRY "try again\n"

#define MSG_TIMEOUT "timeout\n"

int main(void)

{

char buf[10];

int fd,n,i;

fd=open("/dev/tty",O_RDONLY|O_NONBLOCK);

if(fd<0){

perror("open /dev/tty");

exit(1);

}

for(i=0; i<5; i++){

n=read(fd,buf,10);

if(n>=0)

break;

if(errno!=EAGAIN){

perror("read /dev/tty");

exit(1);

}

sleep(1);

write(STDOUT_FILENO,MSG_TRY,strlen(MSG_TRY));

}

if(i==5)

write(STDOUT_FILENO,MSG_TIMEOUT,strlen(MSG_TIMEOUT));

else

write(STDOUT_FILENO,buf,n);

close(fd);

return 0;

}

4.mmap内存映射

#include

#include

#include

int main(void)

{

int *p;

int fd;

fd=open("hello",O_RDWR);

if(fd<0){

perror("open hello:");

exit(1);

}

p=mmap(NULL,6,PROT_WRITE,MAP_SHARED,fd,0);

if(p==MAP_FAILED){

perror("mmap");

exit(1);

}

close(fd);

p[0]=0x30313233;

munmap(p,6);

return 0;

}

文件映射到内存时文件位置与内存位置是对应的,但内存是以页为单位管理内存的,所以内存一分配最小就是一页大小。我遇到一个问题,举个例子,如果你的文件里面有6个字符,你将这6个字符映射到内存,你向此内存写入8个字符,但文件中还是只有6个字节。

5.ioctl

#include

#include

#include

#include

int main(void)

{

struct winsize size;

if(isatty(STDOUT_FILENO)==0)

exit(1);

if(ioctl(STDOUT_FILENO,TIOCGWINSZ,&size)<0){

perror("ioctl TIOCGWINSZ");

exit(1);

}

printf("%d rows ,%d col\n",size.ws_row,size.ws_col);

return 0;

}

6.fcntl

#include

#include

#include

#include

int main(int argc,char *argv[])

{

int val;

if(argc!=2){

fputs("usage:a.out \n",stderr);

exit(1);

}

if((val=fcntl(atoi(argv[1]),F_GETFL))<0){

printf("fcntl error for fd %d\n",atoi(argv[1]));

exit(1);

}

switch(val & O_ACCMODE){

case O_RDONLY:

printf("read only");

break;

case O_WRONLY:

printf("write only");

break;

case O_RDWR:

printf("read write");

break;

default:

fputs("invalid access mode\n",stderr);

exit(1);

}

if(val & O_APPEND)

printf(", append");

if(val & O_NONBLOCK)

printf(", nonblocking");

putchar('\n');

return 0;

}

以上就是自己在学UNIX高编文件I/O入门练习的几个小代码,后面继续讲解!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值