您的位置:首页 > 其它

Day27、文件夹内容的读取、软连接和硬链接文件、fctl文件锁的操作、Mycp.c

2016-09-03 08:50 351 查看
 

昨天遗留的问题:

33  32 31  30  6f  0a

3   2  1   0   o  \n       

前4个字节变了,因为程序中int*p=(int *)handle;,只改了int 型个字节,int是4个字节

p[0]=0x30313233;

int p 一次访问4个字节

p[0]=0x30313233

int arr[3]

int *p=arr

arr[0]=p[0]

作业:写一个程序,判断计算机是大端还是小端

 

一、          文件夹内容的读取:

文件夹内容是文件夹里的文件

怎么去获取文件夹的内容?

 

打开文件夹:opendir

opendir (3) 3说明不是系统调用,是库函数

#include <sys/types.h>

#include <dirent.h>

DIR *opendir(const char *name);

功能:打开name指定的文件夹

参数:  name:文件夹路径

返回值:

NULL:打开失败,errno被设置

 

关闭文件夹:closedir

closedir (3)

#include <sys/types.h>

#include <dirent.h>

int closedir(DIR *dirp);

参数:  dirp:opendir的返回值

 

读取文件夹的内容:readdir

readdir(3)

#include <dirent.h>

struct dirent *readdir(DIR *dirp);

功能:读取dirp指向的文件夹的内容。调用一次,只能读取一个文件夹

参数:  dirp: opendir的返回值

返回值:

NULL:到达文件夹内容的末尾(即最后一个文件)或发生了错误

如果是EBAD错误发生,说明读取文件夹内容的时候,发生了错误。否则就是到达了文件内容的最后。

struct dirent {

               ino_t          d_ino;          /* inode number */

               off_t          d_off;          /* offset to the next dirent */

               unsigned short  d_reclen;       /* length of this record */

              unsigned char   d_type;        /* type of file; not supported

                                             by all file system types */

               char           d_name[256];  /* filename */

          };

 

举例:遍历文件夹目录 dir.c

  1#include<stdio.h>

  2#include<sys/types.h>

  3#include<dirent.h>

  4int main(int argc,char *argv[]){

 5     DIR *dirp;

 6     struct dirent *dir;

 7     //打开argv[1]文件夹

 8     dirp=opendir(argv[1]);

 9     if(dirp==NULL){

 10        perror("opendir");

 11        return 1;

 12     }

 13    //读取文件夹的内容

 14    while(dir=readdir(dirp))

 15        printf("filename ...  %s\n",dir->d_name);

 16    //关闭文件夹

 17    closedir(dirp);

 18    return 0;

 19 }

tarena@tarena-virtual-machine:~/day27$./a.out  .

filename ...   a.out

filename ...   dir.c

filename ...   ..

filename ...   .

 

Myls.c  !!!!!!

  1#include<stdio.h>

  2#include<sys/types.h>

  3#include<dirent.h>

  4#include<sys/stat.h>

  5#include<unistd.h>

  6int main(int argc,char *argv[]){

 7     DIR *dirp;

 8     struct dirent *dir;

 9     struct stat sb;

 10    //打开argv[1]文件夹

 11    dirp=opendir(argv[1]);

 12    if(dirp==NULL){

 13        perror("opendir");

 14        return 1;

 15     }

 16    //读取文件夹的内容

 17    while(dir=readdir(dirp)){

 18        printf("%s\t",dir->d_name);

 19        stat(dir->d_name,&sb);

 20        printf("%lld\n",(long long)sb.st_size);

 21     }

 22    //关闭文件夹

 23    closedir(dirp);

24     return 0;

 25 }

 

二、          软连接和硬链接文件

硬链接是两个文件的inode相同 

软连接是两个文件的inode不同

举例:为a.txt创立一个硬链接文件b.txt

tarena@tarena-virtual-machine:~/day27$ vi a.txt

 

tarena@tarena-virtual-machine:~/day27$ ln a.txt b.txt

tarena@tarena-virtual-machine:~/day27$ ls -l

总用量 20

-rw-rw-r-- 2 tarena tarena   6  9月  2 11:16 a.txt

-rw-rw-r-- 2 tarena tarena   6  9月  2 11:16 b.txt

tarena@tarena-virtual-machine:~/day27$ cat a.txt

hello

tarena@tarena-virtual-machine:~/day27$ cat b.txt

hello

tarena@tarena-virtual-machine:~/day27$ rm a.txt

tarena@tarena-virtual-machine:~/day27$ ls –l b.txt

-rw-rw-r-- 1 tarena tarena   6  9月  2 11:16 b.txt

为b.txt建立一个软连接c.txt

tarena@tarena-virtual-machine:~/day27$ ln -s b.txt c.txt

tarena@tarena-virtual-machine:~/day27$ ls -al

总用量 24

-rw-rw-r--  1 tarenatarena    6  9月  2 11:16 b.txt

lrwxrwxrwx  1 tarenatarena    5  9月  2 11:22 c.txt -> b.txt

tarena@tarena-virtual-machine:~/day27$ stat b.txt

  文件:"b.txt"

  大小:6            块:8          IO 块:4096   普通文件

设备:801h/2049d       Inode:1199677     硬链接:1

权限:(0664/-rw-rw-r--)  Uid:( 1000/  tarena)   Gid:( 1000/  tarena)

最近访问:2016-09-02 11:22:31.865751119+0800

最近更改:2016-09-02 11:16:15.429761019+0800

最近改动:2016-09-02 11:20:41.193755859+0800

创建时间:-

tarena@tarena-virtual-machine:~/day27$ ^C

tarena@tarena-virtual-machine:~/day27$ stat c.txt

  文件:"c.txt" ->"b.txt"

  大小:5            块:0          IO 块:4096   符号链接

设备:801h/2049d       Inode:1199674     硬链接:1

权限:(0777/lrwxrwxrwx)  Uid:( 1000/  tarena)   Gid:( 1000/  tarena)

最近访问:2016-09-02 11:22:57.941748959+0800

最近更改:2016-09-02 11:22:19.705750124+0800

最近改动:2016-09-02 11:22:19.705750124+0800

创建时间:-

tarena@tarena-virtual-machine:~/day27$ cat c.txt

hello

tarena@tarena-virtual-machine:~/day27$ rm b.txt

tarena@tarena-virtual-machine:~/day27$ cat c.txt

cat: c.txt: 没有那个文件或目录

结论:软连接是windows下的快捷方式,硬链接是同一个文件,不同的inode

硬链接不能跨分区(因为同一个inode只能在一个文件系统里),软连接可以跨分区。

(用a.txt建立硬链接b.txt,删了其中一个,另外一个都存在

用b.txt建立软连接c.txt,若删了c.txt,b.txt仍然存在,但删了b.txt,c.txt内容就没了,因为b.txt的inode里的内容是c.txt的文件名)

 

link (2)2是系统调用函数

NAME

link - makea new name for a file

SYNOPSIS

#include <unistd.h>

int link(const char *oldpath, const char*newpath);

举例: 建立硬链接:hardlink.c

  1#include<stdio.h>

  2#include<unistd.h>

  3int main(int argc,char *argv[]){

 4     int ret;

 5     ret=link(argv[1],argv[2]);

 6     if(ret==-1){

 7        perror("link");

 8         return 1
4000
;

 9     }

 10    printf("har link sucessful...\n");

 11    return 0;

 12 }

tarena@tarena-virtual-machine:~/day27$ via.txt

tarena@tarena-virtual-machine:~/day27$ cata.txt

hello

tarena@tarena-virtual-machine:~/day27$./a.out a.txt b.txt

hardlink sucessful...

tarena@tarena-virtual-machine:~/day27$ ls-l

总用量 24

-rwxrwxr-x 1 tarena tarena 7232  9月  2 11:36 a.out

-rw-rw-r-- 2 tarena tarena    6  9月  2 11:37 a.txt

-rw-rw-r-- 2 tarena tarena    6  9月  2 11:37 b.txt

-rw-rw-r-- 1 tarena tarena  234  9月 2 11:36 hardlink.c

 

三、          fctl文件锁的操作(死锁)

多个进程对同一个文件的同一个区域的访问只能同时读,其它的读写访问操作都不能同时进行。(能同时读,但不能一个读其它写,也不能多个进程同时写

通过加锁的方法来解决资源互斥的问题。

锁分为建议锁 / 强制锁两种

建议锁:系统提供了这个功能,大家可用可不用

按照对资源的访问方式又分为两种:读锁(共享锁)/ 写锁(互斥锁)

临界资源:多个进程需要同时进行访问的资源

同步:事情A和事情B,先完成一个,然后再去完成另一个,称为同步。(有顺序)

异步:多个事情可以无序执行。(无顺序)

fcntl (2) fd control  对文件描述符的控制 

#include <unistd.h>

#include <fcntl.h>

int fcntl(int fd, int cmd, ... /* arg */ );

功能:操作处理文件描述符

参数:

fd:要操作的文件描述符

cmd:对文件描述符的操作指令

…. :可变参数。根据cmd判断是否需要参数,需要什么样的参数

返回值:

0:成功

-1:代表失败,errno被设置

Advisory locking

F_GETLK:获取锁信息(看看要操作的文件是不是有锁,是否已被别的进行占用)

F_SETLK:设置锁信息

F_SETLKW:设置锁信息,但是是阻塞设置。等待互斥锁释放

struct flock{

               short l_type;    F_RDLCK,F_WRLCK, F_UNLCK 类型

               short l_whence;  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;    /* PIDof process blocking our lock  进程号

                                   (F_GETLKonly) */

               ...

};

注意:

1、不能在同一个进程里加多个锁

2、锁的类型和文件的打开方式要一致

3、进程结束后,添加的锁全部消失

基于上述信息,实验代码参见processA.c   processB.c

processA.c

  1#include<stdio.h>

  2#include<sys/stat.h>

  3#include<sys/types.h>

  4#include<fcntl.h>

  5#include<unistd.h>

  6int main(){

 7     int fd;

 8     //以只读的方式打开文件

 9    fd=open("a.txt",O_RDONLY);

 10    if(fd==-1){

 11        perror("open");

 12        return 1;

 13     }

 14    //声明一个锁变量,并初始化变量

 15    struct flock lock;

 16    lock.l_type=F_RDLCK;//读锁

 17    lock.l_whence=SEEK_SET;

 18    lock.l_start=0;

 19    lock.l_len=0;

 20    //为文件描述符fd添加一把读锁

 21    if(fcntl(fd,F_SETLK,&lock)==-1){//若添加失败

 22        perror("fcntl");

 23        return 2;

24     }

 25    //若成功

 26    printf("添加读锁成功...\n");

 27    sleep(20);

 28    close(fd);

 29 }

 

processB.c

  1#include<stdio.h>

  2#include<sys/stat.h>

  3#include<sys/types.h>

  4#include<fcntl.h>

  5#include<unistd.h>

  6int main(){

 7     int fd;

 8     //以写的方式打开文件

 9    fd=open("a.txt",O_RDWR|O_CREAT,0644);

 10    if(fd==-1){

 11        perror("open");

 12        return 1;

 13     }

 14     //声明一个锁变量,并初始化变量

 15    struct flock lock;

 16    lock.l_type=F_WRLCK;//写锁

 17    lock.l_whence=SEEK_SET;

 18    lock.l_start=0;

 19    lock.l_len=0;

 20    //为文件描述符fd添加一把写锁,如果文件有其他锁,则等到文件锁释放再加锁

 21    if(fcntl(fd,F_SETLKW,&lock)==-1){//若添加失败

 22         perror("fcntl");

 23        return 2;

 24     }

 25    //若成功

 26    printf("添加写锁成功...\n");

 27    sleep(20);

 28    close(fd);

 29 }

tarena@tarena-virtual-machine:~/day27$ gccprocessA.c -o pa

tarena@tarena-virtual-machine:~/day27$ gccprocessB.c -o pb

在第一个终端里输入指令:

tarena@tarena-virtual-machine:~/day27$ ./pa

在第二个终端里输入指令:

tarena@tarena-virtual-machine:~/day27$ ./pb

pa对文件a.txt加了文件读锁,pb等着给文件a.txt加写锁,20秒后,进程pa结束,读锁释放,则pb对a.txt加写锁。

 

若processB.c中改成

21                 if(fcntl(fd,F_SETLK,&lock)==-1)

则processA.c加过读锁后,processB加锁失败

tarena@tarena-virtual-machine:~/day27$ ./pb

fcntl: Resource temporarily unavailable    因为去掉了SETLKW中的W,waiting,就不等待

 

 

processC.c

  1#include<stdio.h>

  2#include<sys/stat.h>

  3#include<sys/types.h>

  4#include<fcntl.h>

  5#include<unistd.h>

  6int main(){

 7     int fd;

 8     //以只读的方式打开文件

 9    fd=open("a.txt",O_RDONLY);

 10    if(fd= = -1){

 11        perror("open");

 12        return 1;

 13     }

 14    //声明一个锁变量,并初始化变量

 15    struct flock lock;

 16    lock.l_type=F_RDLCK;//读锁

 17     lock.l_whence=SEEK_SET;

 18    lock.l_start=0;

 19    lock.l_len=0;

 20    //为文件描述符fd添加一把读锁

 21    if(fcntl(fd,F_SETLK,&lock)==-1){//若添加失败

 22        perror("fcntl");

 23        return 2;

24     }

 25    //若成功

 26    printf("添加读锁成功...\n");

 27  //  sleep(20);    去掉

 28    close(fd);

 29 }

结果是processA.c对a.txt加读锁在等待20秒的时候,processC.c对文件直接加了读锁

说明,可以同时对文件加读锁

 

四、知识杂项

access (2)  系统调用

NAME

       access - check real user's permissionsfor a file

SYNOPSIS

       #include <unistd.h>

       int access(const char *pathname, intmode);

功能:测试一个进程对文件的操作权限

参数:pathname:文件路径

mode :文件权限

返回值:

0:代表成功

-1:失败,error被设置

vi access.c

  1 #include<stdio.h>

  2 #include<sys/stat.h>

  3 #include<sys/types.h>

  4 #include<unistd.h>

  5 int main(int argc,char *argv[]){

  6     if(access(argv[1],F_OK)==0)

  7        printf("file ok...\n");

  8    if(access(argv[1],W_OK)==0)

  9        printf("file write...\n");

 10    if(access(argv[1],R_OK)==0)

 11        printf("file read...\n");

 12    if(access(argv[1],X_OK)==0)

 13         printf("file exetive...\n");

 14    return 0;

 15 }

tarena@tarena-virtual-machine:~/day27$gcc access.c -o access

tarena@tarena-virtual-machine:~/day27$./access a.txt

file ok...

file write...

file read...

tarena@tarena-virtual-machine:~/day27$ls -l a.txt

-rw-rw-r-- 2tarena tarena 6  9月 2 11:37 a.txt

 

 

!!!!

Mycp.c

  1 #include<stdio.h>

  2 #include<sys/stat.h>

  3 #include<sys/types.h>

  4 #include<unistd.h>

  5 #include<strings.h>

  6 #include<fcntl.h>

  7 long int fcp(int sfd,int dfd);

  8 int main(int argc,char *argv[]){

  9    int sfd,dfd;

 10    int ret;

 11    int flags=O_RDWR|O_CREAT|O_TRUNC;

 12    sfd=open(argv[1],O_RDONLY);

 13    dfd=open(argv[2],flags,0644);

 14    if(sfd==-1||dfd==-1){ //要传的这些参数要在函数外面做检测

 15        perror("open");

 16     }

 17    ret=fcp(sfd,dfd);

 18    if(ret==-1){

 19        printf("文件复制失败\n");

 20        return 1;

 21     }

 22    close(sfd);

 23    close(dfd);

24     return 0;

 25 }

 26 /*

 27 功能:复制sfd文件的内容到dfd中

 28 sfd:源文件

 29 dfd:目标文件

 30 返回值:

 31 文件的大小

 32 -1:代表出错

 33  */

 34 long int fcp(int sfd,int dfd){

 35    char buf[1024]={0};

 36    int r_cnt,w_cnt;

 37    long sum=0;

 38    char *tmp;

 39 /* r_cnt=read(sfd,buf,1024);

 40    1024是想读的,r_cnt是真实读到的

 41    w_cnt=write(dfd,buf,r_cnt);

 42    r_cnt是想写的,w_cnt是真实写入的   */

 43    while((r_cnt=read(sfd,buf,1024))!=0){

 44        tmp=buf;

 45        while((w_cnt=write(dfd,tmp,r_cnt))!=0){

 46            r_cnt=r_cnt-w_cnt;

 47            tmp+=w_cnt;

 48            sum+=w_cnt;

 49        }

 50        bzero(buf,1024);

 51     }

 52    return sum;

 53 }

tarena@tarena-virtual-machine:~/day27$gcc mycp.c -o mycp

tarena@tarena-virtual-machine:~/day27$./mycp mycp.c mycp.2  成功复制文件

自己练习:

unlink

rename

symlink  软链接

chdir

mkdir

rmdir
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐