程序设计面试题_01-Linux文件I/O

1.系统调用和用户编程接口的联系和区别是什么?
答:
(1)联系:
操作系统负责管理和分配所有的计算机资源。为了更好地服务于应用程序,操作系统提供了一组特殊接口——系统调用。通过这组接口用户程序可以使用操作系统内核提供的各种功能。例如分配内存、创建进程、实现进程之间的通信等。
用户编程接口通俗的解释就是各种库(最重要的就是C库)中的函数。为了提高开发效率,C库中实现了很多函数。这些函数实现了常用的功能,供程序员调用。这样一来,程序员不需要自己编写这些代码,直接调用库函数就可以实现基本功能,提高了代码的复用率。使用用户编程接口还有一个好处:程序具有良好的可移植行。
(2)区别
用户程序向操作系统提出请求的接口就是系统调用。所有的操作系统都会提供系统调用接口,只不过不同的操作系统提供的系统调用接口各不相同。Linux系统调用接口非常精简,它继承了UNIX系统调用中最基本和最有用的部分。
用户编程接口(API)在实现时,通常都要依赖系统调用接口。例如,创建进程的A PI函数fork()对应于内核空间的sys_fork()系统调用。很多API函数需要通过多个系统调用来完成其功能。还有一些API函数不需要调用任何系统调用。

2.标准I/O有哪些特点?
答:
(1)通过缓冲机制减少系统调用,从而提高效率
(2)缓冲类型:全缓冲、行缓冲、无缓冲
(3)调用c标准中提供的库函数

3.分别用字符方式、按行访问方式和按对象读写方式实现文件的复制

按字符方式

//用字符方式实现文件的复制
int main(int argc, const char *argv[])
{
	if(argc < 3)
	{
		printf("Input Error: %s  \n",argv[0]);
	}

	FILE *fp_src_r, *fp_dest_w;

	fp_src_r = fopen(argv[1], "r");
	if(fp_src_r == NULL)
	{
		perror(" Src_File Open fail");
		return -1;
	}

	fp_dest_w = fopen(argv[2],"w");
	if(fp_dest_w == NULL)
	{
		perror("Dest_File Open fail");
		return -1;
	}

	char ch;

	while( (ch = fgetc(fp_src_r)) != EOF )
	{
		fputc(ch, fp_dest_w);
	}

	fclose(fp_src_r);
	fclose(fp_dest_w);

	return 0;
}

按行访问方式

//用按行访问方式实现文件的复制

#define N (64)

int main(int argc, const char *argv[])
{
	if(argc < 3)
	{
		printf("Input Error: %s   \n",argv[0]);
	}

	FILE *fp_src_r, *fp_dest_w;

	fp_src_r = fopen(argv[1], "r");
	if(fp_src_r == NULL)
	{
		perror(" Src_File Open fail");
		return -1;
	}

	fp_dest_w = fopen(argv[2],"w");
	if(fp_dest_w == NULL)
	{
		perror("Dest_File Open fail");
		return -1;
	}

	char ch[N];
	
	while( fgets(ch, N, fp_src_r) != NULL )
	{
		fputs(ch, fp_dest_w);
	}

	fclose(fp_src_r);
	fclose(fp_dest_w);

	return 0;
}

按对象读写方式
#define N 64

//按对象读写方式实现文件的复制

int main(int argc, const char *argv[])
{
	
	if(argc < 3)
	{
		printf("Input Error: %s   \n",argv[0]);
	}

	FILE *fp_src_r, *fp_dest_w;

	fp_src_r = fopen(argv[1], "r");
	if(fp_src_r == NULL)
	{
		perror(" Src_File Open fail");
		return -1;
	}

	fp_dest_w = fopen(argv[2],"w");
	if(fp_dest_w == NULL)
	{
		perror("Dest_File Open fail");
		return -1;
	}
	
	int n = 0;
	char buf[N];

	while( (n=fread(buf, sizeof(char), N, fp_src_r)) > 0)
	{
		fwrite(buf, sizeof(char), N, fp_dest_w);
	}
	
	fclose(fp_src_r);
	fclose(fp_dest_w);

	return 0;

}

4.统计一个文本文件包含多少行

#define N 128
 
int main(int argc, const char *argv[])
{
	if(argc < 2)
	{
		printf("Input Error: %s   \n",argv[0]);
	}
	
	FILE *fp_dest_r;

	fp_dest_r = fopen(argv[1], "r");

	if(fp_dest_r == NULL)
	{
		perror(" Dest_File Open fail");
		return -1;
	}
	
	char buf[N];
	int line =0;
	while(fgets(buf, N, fp_dest_r) != NULL)
	{
		if(buf[strlen(buf) -1] == '\n')
		{
			line++;
		}
	}
	
	printf("line = %d\n",line);
	
	fclose(fp_dest_r);
}

5.每隔1秒向文件test.txt中写如当前系统时间
//题目一:每隔1秒向文件test.txt中写如当前系统时间

#define N 64

int main(int argc, const char *argv[])
{
	FILE *fp;
	int line = 0;
	char buf[N];
	time_t Time;
	struct tm *tp;

	if((fp = fopen("abc.txt","a+")) == NULL)
	{
		perror("fopen");
		return -1;
	}

	while(fgets(buf, N, fp) != NULL)
	{
		if(buf[strlen(buf)-1] == '\n')
		{
			line++;
		}
	}

	while(1)
	{
		time(&Time);
		tp = localtime(&Time);
 		fprintf(fp, "%02d, %d-%02d-%02d %02d:%02d:%02d\n", ++line,\
				tp->tm_year+1900, tp->tm_mon+1,\
				tp->tm_mday, tp->tm_hour,\
				tp->tm_min, tp->tm_sec);

		fflush(fp);
		sleep(1);

	}
	
	fclose(fp);
	return 0;
}

6.利用stat函数实现下命令ll的功能

#include 
#include 
#include 
#include 
#include 
#include 
#include 




int main(int argc, const char *argv[])
{
	if(argc < 2)
	{
		printf(" Input Error %s \n",argv[0]);
		return -1;
	}

	struct stat st;//保存获取的文件的属性
	int ret = lstat(argv[1], &st);//获取文件的属性

	if( -1 == ret)
	{
		perror("stat");
		return -1;
	}

	//通过st_mode的值判断文件类型
	switch(st.st_mode & S_IFMT)
	{
	case S_IFREG:
		printf("-");
		break;
	case S_IFDIR:
		printf("d");
		break;
	default:
		break;

	}
	
	//文件的权限
	int i=0;
	for(i=8; i>=0; i--)
	{
		if(st.st_mode & (1<pw_name);

	struct group *gp = getgrgid(st.st_gid);
	printf(" %s",gp->gr_name);

	printf(" %ld",st.st_size);
	printf(" %s %s",argv[1], ctime(&(st.st_mtime)));


	return 0;
}

1、简述虚拟文件系统在Linux系统中的位置和通用文件系统模型。
答:
(1)Linux系统成功的关键因素之一就是具有与其他操作系统和谐共存的能力。Linux的文件系统由两层结构构建:第一层是虚拟文件系统(VFS),第二层是各种不同的具体的文件系统。
VFS就是把各种具体的文件系统的公共部分抽取出来,形成一个抽象层,是系统内核的一部分。它位于用户程序和具体的文件系统之间。它对用户程序提供了标准的文件系统调用接口,对具体的文件系统(比如:Ext2、FAT32等),它通过一系列的对不同文件系统通用的函数指针来调用对应的文件系统函数,完成相应的操作。任何使用文件系统的程序必须通过这层接口来访问。通过这样的方式,VFS就对用户屏蔽了底层文件系统的实现细节和差异。
(2)通用文件系统类型: Ext4、Ext3

2、文件I/O和标准I/O之间有什么区别?
答:文件I/O又称为低级磁盘I/O,遵循POSIX相关标准。任何兼容POSIX标准的操作系统上都支持文件I/O。标准I/O被称为高级磁盘I/O,遵循ANSI C 相关标准。只要开发环境中有标准C库,标准I/O就可以使用。(Linux中使用的是GLIBC,它是标准C库的超集。不仅包含ANSI C中定义的函数,还包括POSIX标准中定义的函数。因此,Linux下既可以使用标准I/O,也可以使用文件I/O)。
通过文件I/O读写文件时,每次操作都会执行相关系统调用。这样处理的好处是直接读写实际文件,坏处是频繁的系统调用会增加系统开销。标准I/O可以看成是在文件I/O的基础上封装了缓冲机制。先读写缓冲区,必要时再访问实际文件,从而减少了系统调用的次数。
文件I/O中用文件描述符表示一个打开的文件,可以访问不同类型的文件如普通文件、设备文件和管道文件等。而标准I/O中用FILE(流)表示一个打开的文件,通常只用来访问普通文件。

你可能感兴趣的:(程序设计面试题)