open
夔庆
2023-12-01
linux 下 调用open函数返回一个文件描述符,这个open操作是仅仅生成一个标识指向该文件?还是将该文件的内容全部或部分调入cache??
一个指向该文件的标识.
实际上, open的路径为:
open->sys_open->getname->get_unused_fd->file->open->open_namei->dentry_open->fd_install
最后的fd_install设置fd数组的指针, 让fd指向由filp_open返回的文件对象的地址. 即设置current->files->fd[num]
只是生成一个相应的结构体,这个结构体记录了用户操作文件所需的数据和函数入口,返回的整型值表示这个结构体在数组中的下标位置.
另外我还想再问一个问题,open文件后,仅仅生成一个文件描述符,那当我们read的时候,分配一个空间暂时存放数据(文件很大),是仅仅读取指定大小的数据到内存,然后再传给分配的暂时空间,还是要读取指定地址范围内一块数据,然后从中再读取指定字节数据到暂时空间??
块设置在读取的时候,并不是一个一个字节的读,因此实际读出的数据比用户所请求的要多一些,不过用户是感知不到的..
open之后内核还会分配一个FILE结构体
FILE 结构体是用户空间的,struct file 倒是在内核空间。
程序的目的是实现从一个txt文件当中逐行读取放到一个数组中,然后问题出现了,在现在的平台上fopen无法打开文件,于是就用linux中的open打开,文件是打开了,下面是代码:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
char* filename[100];
int len=0;
int readData(int fd,char *buf)
{
return read(fd,buf,676);
}
void getAllFileName()
{
int j;
for(j=0;j<100;j++)
{
filename[j]=(char*)malloc(sizeof(char)*100);
}
int i=0;
int fd=open("e:/file.txt",O_RDONLY);
if(fd<0){
printf("file open failed.\n");
return;
}
char *buf=(char*)malloc(sizeof(char)*1024);
readData(fd,buf);
printf("buf:\n%s\n--------\n",buf);
char *temp=NULL;
while((temp=strtok(buf,"\n"))!=NULL){
temp=filename[len++];
}
close(fd);
}
int main()
{
getAllFileName();
int i=0;
for(;i<len;i++){
printf("%s\n",filename[i]);
}
for(i=0;i<100;i++){
free(filename[i]);
}
system("pause");
return 0;
}
问题:
1,后面怎么会打印两个相同的呢?
2, while((temp=strtok(buf,"\n"))!=NULL){ 这里编译器提示[Warning] assignment makes pointer from integer without a cast ,运行结果是字符串分割失败,请问我这样调用strtok有什么不对吗?
file.txt:
AliIM2010_taobao(6.50.04C).exe
compose.html
constants.js
details.html
details_common.js
details_compose.js
details_view_controller.js
errorMessage.js
FeiQ.exe
foxmail65.exe
gadget.gmanifest
Gmail.gg.zip
GmailConfig.exe
httpRequest.js
Install_WLMessenger.exe
ITxiazai_GoogleDesktopSetup.exe
jdeclipse_update_site.zip
KuGou.exe
loginView.js
mailView.js
main.js
main.xml
message.js
netbeans-6.8-ml-javase-windows.exe
pdf_setup.zip
qhelper.exe
QQ2010SP3.1.exe
QQPCMgr_Setup_44_816_60143.exe
QQWubi_Setup_13_283.exe
resources.js
responseData.js
setup.exe
size_details_view.xml
thread.js
ui_mailView.js
urlBuilder.js
utils.js
read函数原型:
ssize_t read(int fd,void *buf,size_t count)
1、如果读取成功,则返回实际读到的字节数。这里又有两种情况:一是如果在读完count要求字节之前已经到达文件的末尾,那么实际返回的字节数将小于count值,但是仍然大于0;二是在读完count要求字节之前,仍然没有到达文件的末尾,这是实际返回的字节数等于要求的count值。
2、如果读取时已经到达文件的末尾,则返回0。
3、如果出错,则返回-1。
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define NUM 60
void getAllFileName()
{
int fd=open("e:/file.txt",O_RDONLY);
if(fd <0){
printf("file open failed.\n");
return;
}
char *buf=(char*)malloc(sizeof(char)*100);
int count=0;
while(count!=-1&&(count=read(fd,buf,NUM)))
{
printf("count=%d\nbuf=\n%s\n",count,buf);
}
free(buf);
close(fd);
}
int main()
{
getAllFileName();
system("pause");
return 0;
}
问题应该出在strtok的使用上。
C/C++ code
char *tmp=NULL;
tmp = strtok(buf, "\n");
while (tmp != NULL)
{
int k;
buf = NULL; // [color=#FF0000]要置为NULL[/color]
printf("file name: %s\n", tmp); // 可以正确打印文件名称
//filename[k++] = tmp;
//printf("%s\n", filename[k++]); //这里打印不了。
tmp = strtok(buf, "\n");
}
将楼主代码进行几处修改,可以正常获取文件名称,但是存在内存泄漏。
1、return read(fd,buf,1024); // 将数值改大一些
2、 while((temp=strtok(buf,"\n"))!=NULL){
buf = NULL;
filename[len++]=temp;
//temp=filename[len++];
} 将buf置为NULL(应该在while前面执行一次strtok,避免每次都给buf赋值)。
3、 for(i=0;i<100;i++){
free(filename[i]);
}
这个free造成double free的错误,如果注释掉,造成内存泄漏。
gcc & fc10测试,同时使用valgrind工具。