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 <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <strings.h>

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 <unistd.h>
#include <stdlib.h>

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 <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>

#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 <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>

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 <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

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 <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc,char *argv[])
{
	int val;
	if(argc!=2){
		fputs("usage:a.out <descriptor#>\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入门练习的几个小代码,后面继续讲解!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值