第三講 文件管理
文件模式
常規文件
管道(IPC):Linux系統的進程間通信的一種機制,FIFO的文件,有兩種管道:無名管道和命名管道
目錄文件:以文件的方式進行操作
設備文件:大多數物理設備都用文件來表示,有兩種設備文件:塊設備和字符設備
符號連接:包含到定義文件的特殊路徑,類似於windows下的快捷方式
套接字:進程間通信的機制
基本的文件操作
inode(信息節點)
內核信息節點(in-core inode):不同類型的文件的內核信息節點都是相同的
磁盤信息節點(on-disk inode):不同文件系統類型具有不同的磁盤信息節點
當一個進程打開磁盤中的文件,磁盤信息節點就轉換成內核信息節點,如果內核信息節點被修改,則該節點的信息將被傳回磁盤信息節點
1. 文件模式
文件模式定義
低12位:表示訪問權限,用於管理對文件的訪問和文件權限的修飾符
寫成6個8進制數
例:
041777
100755
文件訪問權限
3個訪問控制位
chmod
例
-rwx------ 1 root root 218 5月 22 20:49 forkd.c
[root@localhost ch02]# chmod 777 forkd.c
-rwxrwxrwx 1 root root 218 5月 22 20:49 forkd.c
文件權限修飾符與類型
是一個位掩碼,表示setuid、setgid、stiky
文件類型
sys/stat.h
進程的umask
#include<sys/stat.h>
int umask(int newmask);
例
[root@localhost tmp]# touch ex1
[root@localhost tmp]# ls –l
-rw-rw-r-- 1 root root 0 5月 22 21:56 ex1
[root@localhost tmp]#umask 077
[root@localhost tmp]# touch ex2
-rw-rw-r-- 1 root root 0 5月 22 21:56 ex1
-rw------- 1 root root 0 5月 22 21:58 ex2
2.基本的文件操作
文件描述符
stdin、stdout、stderr
#include <unistd.h>
STDIN_FILENO, STDOUT_FILENO,STDERR_FILENO
操作文件的參數
關閉文件
int close(int fd);
打開文件:
#include <fcntl.h>
int open(char *pathname, int flags, mode_t mode);
int create(char *pathname, mode_t mode);
flags: O_RDONLY, O_RDWR, O_WRONLY, O_CREATE, O_EXCL ,O_NOCTTY, O_TRUNC, O_APPEND, O_NONBLOCK, O_SYNC
open(pathname, O_CREAT|O_WRONLY|O_TRUNC, mode)
文件的讀寫與位置指針的移動
#include <unistd.h>
size_t read(int fd, void *buf, size_t length);
size_t write(int fd, const void *buf, size_t length);
例
// 寫文件
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
int fd;
if ((fd=open("rwexm",O_TRUNC|O_CREAT|O_WRONLY,0644))<0)
{
perror("open");
_exit(1);
}
if (write(fd,"hello world/n",13) != 13)
{
perror("write");
_exit(1);
}
close(fd);
return 0;
}
// 讀文件
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
int size = 13;
char buffer[size];
int fd;
if ((fd = open("rwexm",O_RDONLY,0644)) < 0)
{
perror("open");
_exit(1);
}
if (read(fd,buffer,sizeof(buffer)) < 0){
perror("read");
_exit(1);
}
printf(buffer);
close(fd);
return 0;
}
int lseek(int fd, off_t offset, int whence);
SEEK_SET, SEEK_CUR, SEEK_END
局部讀寫
例
模擬實現cat系統命令
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
int main(int argc, char **argv)
{
int fd, len;
char buf[1024];
if ( argc < 2)
{
printf("at least 1 para/n");
return 0;
}
if ((fd = open(argv[1],O_RDONLY,0666)) < 0)
{
perror("open");
_exit(1);
}
while ((len = read(fd,buf,sizeof(buf))) > 0)
{
if (write(1,buf,len) != len)
{
perror("write");
close(fd);
_exit(1);
}
}
if (len < 0)
{
perror("read");
close(fd);
_exit(1);
}
close(fd);
return 0;
}
// 縮短文件
int truncate(const char *pathname, size_t length);
int ftruncate(int fd, size_t length);
// 同步:執行該函數後立刻將數據寫回到硬件
int fsync(int fd)
int fdatasync(int fd)
查詢和修改inode信息
查詢inode信息
#include <sys/stat.h>
int stat(const char *pathname, struct stat *statbuf);
int lstat(const char *pathname, struct stat *statbuf);
int fstat(int fd, struct stat *statbuf);
struct stat成員
dev_t st_dev unsigned long st_block
ino_t st_ino time_t st_atime
mode_t st_mode time_t st_mtime
nlink_t st_nlink time_t st_ctime
uid_t st_uid unsigned long st_blksize
gid_t st_gid
dev_t st_rdev
off_t st_size
例
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <time.h>
#include <unistd.h>
#define TIME_STRING_BUF 50
char *timeString(time_t t, char*buf)
{
struct tm *local;
local = localtime(&t);
strftime(buf, TIME_STRING_BUF,"%c",local);
return buf;
}
int statFile(const char *file)
{
struct stat statbuf;
char timeBuf[TIME_STRING_BUF];
if (lstat(file,&statbuf))
{
fprintf(stderr,"could not lstat %s:%s/n",file,strerror(errno));
return 1;
}
printf("filename: %s/n",file);
printf("on device: major %d/minor %d inod number: %ld/n",major(statbuf.st_dev),minor(statbuf.st_dev),statbuf.st_ino);
printf("size :%x-10ld type:%07o permissions %05o/n",statbuf.st_size,statbuf.st_mode&S_IFMT,statbuf.st_mode&~(S_IFMT));
printf("owner:%d group:%d number of links:%d/n",statbuf.st_uid,statbuf.st_gid,statbuf.st_nlink);
printf("chnge time:%s/n",timeString(statbuf.st_ctime,timeBuf));
printf("modified time:%s/n",timeString(statbuf.st_mtime,timeBuf));
printf("access time:%s/n",timeString(statbuf.st_atime,timeBuf));
return 0;
}
int main(int argc, const char **argv)
{
int i;
int rc = 0;
for (i = 1; i < argc; i++)
{
rc |= statFile(argv[i]);
if ((argc -i) > 1)
{
printf("/n");
}
}
return rc;
}
#include <unistd.h>
int access(const char *pathname, int mode);
正確返回0,出錯返回EACCESS
#include <sys/stat.h>
int chmod(const char *pathname, mode_t mode);
int fchmod(int fd, mode _t mode);
返回EPERM
#include <unistd.h>
int chown(const char *pathname, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group);
#include <utime.h>
int utime(const char *pathname, strcut utimbuf *buf);
#include<sys/time.h>
int utimes(const char *pathname, struct timeval *tvp);
struct utimbuf
{
time_t actime;
time_t modtime;
}
struct timeval
{
long tv_sec;
long tv_usec;
}
ext3擴展屬性
EXT3_APPEND_FL
EXT3_IMMUTABLE_FL
EXT3_NODUMP_FL
EXT3_SYNC_FL
#include <sys/ioctl.h>
#include <linux/ext3_fs.h>
int ioctl(int fd, int request, void *arg);
EXT3_IOC_GETFLAGS, EXT3_IOC_SETFLAGS
例:
操作目錄項
#include <fcntl.h>
#include <unistd.h>
int mknod(const char *pathname, mode_t mode, dev_t dev);
S_IFIFO, S_IFBLK, S_IFCHR
<sys/sysmacros.h> makedev(major, minor), major(), minor()
/*創建硬鏈接*/
#include <unistd.h>
int link(const char *origpath, const char *newpath);
/*創建符號連接*/
#include <unistd.h>
int sysmlink(const char *origpath, const char *newpath);
int readlink(const char *pathname, char *buf, size_t bufsize);
chown(), lstat(), readlink(), rename(), unlink()
/*刪除文件*/
#include <unistd.h>
int unlink(char *pathname);
int rename(const char *oldpath, const char *newpath);
操作文件描述符和創建無名管道
#include <fcntl.h>
Int fcntl(int fd, int command, long arg);
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_RDONLY);
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_APPEND);
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_APPEND);
/*複製文件描述符*/
int dup(int oldfd);
int dup2(int oldfd, int newfd);
int pipe(int fds[2]);
例
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <unistd.h>
#include <fcntl.h>
void usage(void)
{
fprintf(stderr, "usage:mkmmodexa <path> [b|c|n|p] <major> <minor> /n");
_exit(1);
}
int main(int argc, char **argv)
{
int major = 0, minor = 0;
const char *path;
int mode = 0666;
char *end;
int args;
if (argc < 3 )
{
usage();
}
path = argv[1];
if (!strcmp(argv[2],"b"))
{
mode |= S_IFBLK;
args = 5;
}
else if (!strcmp(argv[2],"c") || !strcmp(argv[2],"m"))
{
mode |= S_IFCHR;
args = 5;
}
else if (!strcmp(argv[2],"p"))
{
mode |= S_IFIFO;
args = 3;
}
else
{
sprintf(stderr, "unknown node type %s/n",argv[2]);
return 1;
}
if (args == 5)
{
major = strtol(argv[3],&end,0);
if (*end)
{
fprintf(stderr,"bad major number %s/n",argv[3]);
return 1;
}
minor = strtol(argv[4],&end,0);
if (*end)
{
fprintf(stderr, "bad major number %s/n",argv[4]);
return 1;
}
}
if (mknod(path, mode, makedev(major, minor)))
{
fprintf(stderr, "mkmod failed:%s/n",strerror(errno));
return 1;
}
return 0;
}