Linux 磁盘文件内容管理

         要去访问磁盘的文件,必须通过系统调用来返回一个与该文件相关联的 ID,这个ID 就是文件描述符file descriptor。Linux 操作系统提供了open 系统调用,任何的进程要去访问一个文件,首先使用open 打开这个文件,系统将返回一个编号,即与这个文件相关联的文件描述符。
                         (1)用户程序从用户空间向内核空间提交了打开申请。
                         (2)操作系统会在内核中去检查请求是否合法,如果合法,在内核中申请这个打开文件相关的信息(读写位置,在磁盘中的位置…..全用struct files 来存储)。并且添加到当前进程的PCB 块中的打开文件列表数组中。对应的这个数组下标即文件描述值。
                          (3)将这个文件描述符返回给用户空间,用户空间接下来对这个文件进行读写就通过这个编号值。

                            系统默认为每个进程打开了三个文件:
printf/scanf  /错标准误输出


                文件描述符0(标准输入,键盘 STDIN_FILENO),1(标准输出,显示器STDOUT_FLIENO),2(标准错误输出,显示器STDERR_FILENO)


二 、IO 系统调用函数
建立与断开联系 open/close
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, //打开文件路径
int flags); //打开的方式等flags
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, mode_t mode);


只读方式 O_READONLY
只写方式 O_WRITEONLY
读写方式O_RDWR
追加方式O_APPEND
/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
located on an ext2 file system */
#define O_ACCMODE 0003
#define O_RDONLY 00
#define O_WRONLY 01
#define O_RDWR 02
#define O_APPEND 02000
#define O_CREAT 0100 /* not fcntl */
#define O_EXCL 0200 /* not fcntl */
#define O_NOCTTY 0400 /* not fcntl */
#define O_TRUNC 01000 /* not fcntl */
#define O_NONBLOCK 04000
#define O_NDELAY O_NONBLOCK
#define O_SYNC 010000
#define FASYNC 020000 /* fcntl, for BSD compatibility */
#define O_DIRECT 040000 /* direct disk access hint - currently ignored */
#define O_LARGEFILE 0100000 //大于2G 的文件
#define O_DIRECTORY 0200000 /* must be a directory */
#define O_NOFOLLOW 0400000 /* don't follow links */
#define O_ATOMICLOOKUP 01000000 /* do atomic file lookup */


int open(const char *pathname, int flags, mode_t mode);
新创建一个文件的真正权限是 mode & ~umask
这个文件打开成功,将返回一个新的文件描述符值,后面针对这个文件的操作就使用这个文件描述
符。
读写文件内容 read/write
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
//从fd 所指向的文件中读取count 字节到buf 为首地址的内存空间中。
ssize_t write(int fd, const void *buf, size_t count);
//往fd 所指向的文件中写入count 字节,这个内容存放在buf 为首地址的内存空间中。

(1) 打开一个文件 并输出文件描述符

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<funtl.h>


int main(int argc,char* argv[])
{
int fd;
fd = open(argv[1],O_RDONLY|O_CREAT,0644);
if(-1 == fd)
{
perror("open");
exit(EXIT_FAILURE);
}
printf("fd:%d\n",fd);
close(fd);
}


(2)把一个文件复制到另一个文件中  只可复制1024大小的文件:

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<funtl.h>


int main(int argc,char* argv[])
{
if(argc != 3)
{
printf("pls input message format as:%s src dst\n",argv[0]);
exit(EXIT_FAILURE);
}
int fd_src, fd_dst;
fd_src = open(argv[1],O_RDONLY,0644);
if(-1 == fd_src)
{
perror("open");
exit(EXIT_FAILURE);
}
fd_dst = open(argv[2],O_WRONLY|O_CREAT,0644);
if(-1 == fd_dst)
{
perror("open det");
exit(EXIT_FAILURE);
}

char buf[1024];
int ret = 0;

memset(buf,'\0',1024);

ret = read(fd_src,buf,1024);
write(fd_dst,buf,ret);

close(fd_src);
close(fd_dst);
printf("fd:%d\n",fd_src);
}


(3) 2的改进修改  可复制任意大小的文件

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<funtl.h>


int main(int argc,char* argv[])
{
if(argc != 3)
{
printf("pls input message format as:%s src dst\n",argv[0]);
exit(EXIT_FAILURE);
}
int fd_src, fd_dst;
fd_src = open(argv[1],O_RDONLY,0644);
if(-1 == fd_src)
{
perror("open");
exit(EXIT_FAILURE);
}
fd_dst = open(argv[2],O_WRONLY|O_CREAT,0644);
if(-1 == fd_dst)
{
perror("open det");
exit(EXIT_FAILURE);
}

char buf[1024];
int ret = 0;

while(1)    //每次复制1024 直到复制完成
{
memset(buf,'\0',1024);


       ret = read(fd_src,buf,1024);
       if(ret == -1)
       {
        perror("read"); exit(EXIT_FAILURE);
}else if(ret == 0)
{
break;
}else
           write(fd_dst,buf,ret);
}



close(fd_src);
close(fd_dst);
printf("fd:%d\n",fd_src);
}



文件位置的修改 lseek
对当前文件的读写位置进行定位。可以在文件中添加空洞。
off_t lseek(int fd, off_t offset, int whence);
SEEK_SET
The offset is set to offset bytes.
SEEK_CUR
The offset is set to its current location plus offset bytes.
SEEK_END
The offset is set to the size of the file plus offset bytes.
也可以用这个函数来实现文件大小的获取。把文件的读写位置设置为文件结束,因为这个函数返回
当前读写位置距离文件头的偏移字节数。
lseek+write=pwrite
lseek+read =pread
ssize_t pread(int fd, void *buf, size_t count, off_t offset);
ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);



三、 文件描述符操作
(1)复制功能。用处,第9 章管道时会提到重定向的应用 cat test>test.txt。
复制后,两个文件描述符都指向同一个文件表项,即使用这两个文件描述符中的一个就会影响读写
相关的信息。
dup/dup2/fcntl
int dup(int oldfd); //复制oldfd 这个文件描述符,返回在调用此函数前最小未使用的文件描述符的值。

close(0);
dup(3);
这个代码可以实现输入的重定向。默认从0 读数据,现在0 指向的表项被复制为3,这样从0 读实
际上就是从3 指向的文件读,也就实现的输入的重定向。
int dup2(int oldfd, int newfd);
把oldfd 复制为newfd,如果newfd 已经对应一个打开的文件,则先关闭它。
dup2(3,0);


int fcntl(int fd, int cmd, ... /* arg */ );
cmd:F_DUPFD.   复制文件
fd_dup = fcntl(new_copy_fd, F_DUPFD);  将new_copy_fd 这个文件描述符复制给fd_dup;


(2)锁定功能。并发的环境下,除了使用并发的工具来保护共享文件外,也可以使用文件锁。
flock
int flock(int fd, int operation);
LOCK_SH Place a shared lock. More than one process may hold a shared lock for a given file at a
given time.共享读。
LOCK_EX Place an exclusive lock. Only one process may hold an exclusive lock for a given file at a
given time.排它锁。
LOCK_UN Remove an existing lock held by this process.
LOCK_NB 非阻塞式申请。
强调一下,这里指的是锁定文件描述符。锁定这个文件表项。防止被其它的进程访问,锁整个文
件。
如果要锁定某一部分,可以使用 fcntl 函数。
fcntl(fd,F_SETLKW,struct flock*);
第三个参数如下定义:

              struct flock {
...
short l_type; /* Type of lock: F_RDLCK,
F_WRLCK, F_UNLCK */
short l_whence; /* How to interpret l_start: 类似于lseek 函数
SEEK_SET, SEEK_CUR, SEEK_END */
off_t l_start; /* Starting offset for lock */ 起始位置偏移
off_t l_len; /* Number of bytes to lock */ 结束位置偏移
pid_t l_pid; /* PID of process blocking our lock 进程号
(F_GETLK only) */
...
};


(3)属性控制。权限状态,拥有者等。
fcntl:当前的读写状态,当前文件描述符所在的进程等系列信息。参阅书上的5.2.7 内容。
(4)提高效率,同步磁盘。
因此,可以使用 mmap 函数来将某个打开的文件映射到虚拟地址空间,以后操作这个虚拟地址空间
就类似于操作这个文件。

fcntl 锁定文件示例
进程A 进程B
都需要对同一个文件进行写入操作
为了让定入操作是排它的,使用文件锁操作。
本章示例代码:实现大于 2G 的文件的拷贝操作。如果文件大于2G,偏移超过int_32 类型的限制,
为了实现大文件的拷贝,必须使用宏。
(1)在所有的头文件包含加加上
#define _LARGEFILE_SOURCE
#define _FILE_OFFSET_BITS 64
(2)在编译时,加上宏
gcc –D_LARGEFILE64_SOUCR –D_FILE_OFFFSET_BITS=64


下面是一个得到当前cpu利用率的代码:

在Linux中如果要监视一个进程的运行情况,如查看它的CPU使用效率和内存使用情况,就需要从系统的/proc目录的读取一些系统信息

void 
get_system_info(info)
    
 
struct  system_info  * info;
{
    
 char  buffer[ 4096 + 1 
];
    
 int 
 fd, len;
    
 char   * 
p;
    
 int 
 i;

    
 /*  get load averages  */ 

    {
    fd 
 
=  open( " loadavg " , O_RDONLY);
    len 
 =  read(fd, buffer,  sizeof (buffer) - 1 
);
    close(fd);
    buffer[len] 
 =   ' \0 ' 
;

    info
 -> load_avg[ 0  =  strtod(buffer,  & 
p);
    info
 -> load_avg[ 1  =  strtod(p,  & 
p);
    info
 -> load_avg[ 2  =  strtod(p,  & 
p);
    p 
 =  skip_token(p);             /*  skip running/tasks  */ 

    p  
=  skip_ws(p);
    
 if  ( * 
p)
        info
 -> last_pid  = 
 atoi(p);
    
 else 

        info 
-> last_pid  =   - 1 ;
    }

    
 /*  get the cpu time info  */ 

    {
    fd 
 
=  open( " stat " , O_RDONLY);
    len 
 =  read(fd, buffer,  sizeof (buffer) - 1 
);
    close(fd);
    buffer[len] 
 =   ' \0 ' 
;

    p 
 =  skip_token(buffer);             /*  "cpu"  */ 

    cp_time[ 
0  =  strtoul(p,  & p,  0 );
    
    cp_time[
 1  =  strtoul(p,  & p,  0 
);
    cp_time[
 2  =  strtoul(p,  & p,  0 
);
    cp_time[
 3  =  strtoul(p,  & p,  0 
);

    
 /*  convert cp_time counts to percentages  */ 

    percentages( 
4 , cpu_states, cp_time, cp_old, cp_diff);
    }
    
    
 /*  get system wide memory usage  */ 

    {
    
 
char   * p;

    fd 
 =  open( " meminfo " 
, O_RDONLY);
    len 
 =  read(fd, buffer,  sizeof (buffer) - 1 
);
    close(fd);
    buffer[len] 
 =   ' \0 ' 
;

    
 /* 
 be prepared for extra columns to appear be seeking
       to ends of lines 
 */ 

    
    p 
 
=  buffer;
    p 
 = 
 skip_token(p);
    memory_stats[
 0  =  strtoul(p,  & p,  10 );  /*  total memory  */ 

    
    p 
 
=  strchr(p,  ' \n ' );
    p 
 = 
 skip_token(p);
    memory_stats[
 1  =  strtoul(p,  & p,  10 );  /*  free memory  */ 

    
    
    p 
 
=  strchr(p,  ' \n ' );
    p 
 = 
 skip_token(p);
    memory_stats[
 2  =  strtoul(p,  & p,  10 );  /*  buffer memory  */ 

    
    p 
 
=  strchr(p,  ' \n ' );
    p 
 = 
 skip_token(p);
    memory_stats[
 3  =  strtoul(p,  & p,  10 );  /*  cached memory  */ 

    
    
 
for (i  =   0 ; i <   8  ;i ++ ) {
        p
 ++ 
;
        p 
 =  strchr(p,  ' \n ' 
);
    }
    
    p 
 = 
 skip_token(p);
    memory_stats[
 4  =  strtoul(p,  & p,  10 );  /*  total swap  */ 

    
    p 
 
=  strchr(p,  ' \n ' );
    p 
 = 
 skip_token(p);
    memory_stats[
 5  =  strtoul(p,  & p,  10 );  /*  free swap  */ 

    
    }

    
 
/*  set arrays and strings  */ 
    info 
-> cpustates  =  cpu_states;
    info
 -> memory  = 
 memory_stats;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值