open

来源:互联网 发布:天津办公软件培训 编辑:程序博客网 时间:2024/05/01 12:22
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工具。