您的位置:首页 > 编程语言

UNIX环境高级编程(第4章 文件和目录)

2014-09-29 21:43 288 查看

1文件类型

1)普通文件:最常见的文件类型,包含的数据是文本还是二进制数据由处理该文件的应用程序解释。而二进制可执行文件需遵循一种格式,该格式使内核能够确定程序文本和数据的加载位置。
2)目录文件:该文件包含了其他文件的名字以及指向与这些文件有关信息的指针。
3)块特殊文件:该文件类型提供对设备(如磁盘)带缓冲的访问,每次访问以固定长度为单位进行。
4)字符特殊文件:该文件类型提供对设备不带缓冲的访问,每次访问长度可变。
5)FIFO:该类型的文件用于进程间通信,也称为命名管道。
6)套接字:该文件类型用于进程间的网络通信。也可用于一台宿主机上进程之间的非网络通信。
7)符号链接:该文件类型指向另一个文件。

文件相关信息结构:(实际定义随实现有所不同,但基本形式如下)

struct stat {

mode_t st_mode; /*文件类型与文件访问权限*/

ino_t st_ino; /*i节点序列号*/

dev_t st_dev; /*设备号*/

dev_t st_rdev; /*特殊文件设备号*/

nlink_t st_nlink;
/*链接个数*/

uid_t st_uid; /*用户ID*/

gid_t st_gid; /*组ID*/

off_t st_size;/*字节为单位的文件长度,针对普通文件、目录、符号链接*/

time_t st_atime; /*文件数据的最后访问时间*/

time_t st_mtime; /*文件数据的最后修改时间*/

time_t st_ctime; /*i节点状态的最后修改时间*/

blksize_t st_blksize;/*最佳IO块大小*/

blkcnt_t st_blocks; /*磁盘块分配个数*/

}
【1】查看文件类型的代码
#include "apue.h"

int main(int argc, char *argv[])
{
int i;
struct stat buf;
char *ptr;

for (i = 1; i < argc; i++)
{
printf("%s: ", argv[i]);
if (lstat(argv[i], &buf) < 0)
{
err_ret("lstat error");
continue;
}

if (S_ISREG(buf.st_mode))
ptr = "regular";
else if(S_ISDIR(buf.st_mode))
ptr = "diretcory";
else if (S_ISCHR(buf.st_mode))
ptr = "character special";
else if (S_ISBLK(buf.st_mode))
ptr = "block special";
else if (S_ISFIFO(buf.st_mode))
ptr = "fifo";
else if (S_ISLNK(buf.st_mode))
ptr = "symbolic link";
else if (S_ISSOCK(buf.st_mode))
ptr = "socket";
else
ptr = "** unknow mode **";

printf("%s\n", ptr);
}

exit(0);

}
[root]# ./a.out /etc/passwd /etc /dev/initctl /dev/log /dev/tty  /dev/sda /dev/cdrom
/etc/passwd: regular
/etc: diretcory
/dev/initctl: fifo
/dev/log: socket
/dev/tty: character special
/dev/sda: block special
/dev/cdrom: symbolic link
【2】查看文件类型的命令

[root]# ls -l a.out

-rwxrwSrwx1 root root 9017 05-22 12:15 a.out
a.out的详细信息中,有-rwxrwSrwx等10个字符,其中第一个字符表示文件类型,具体如下:
-表示普通文件
d
表示目录
l
表示符号链接文件
b
表示块设备
c
表示字符设备
s
表示套接字
p
表示命名管道(named pipe),即FIFO
2 文件访问权限

a.out的详细信息中,有-rwxrwSrwx等10个字符,其中第2个到第10个字符表示文件访问权限,具体如下:
【1】一般权限

第2~4个字符
表示用户的读、写、执行权限。
第5~7个字符
表示组 的读、写、执行权限。
第8~10个字符
表示其他的读、写、执行权限。
【2】特殊权限
s或S
SUID,Set UID,可执行的文件搭配这个权限,便能得到特权,任意存取该文件的所有者能使用的全部系统资源
s或S
设置在文件上面,其效果与SUID相同,只不过将文件所有者换成用户组,该文件就可以任意存取整个用户组所能使用的系统资源。
t或T
Sticky,/tmp和
/var/tmp目录供所有用户暂时存取文件,亦即每位用户皆拥有完整的权限进入该目录,去浏览、删除和移动文件。
因为SUID、SGID、Sticky占用x的位置来表示,所以在表示上会有大小写之分。加入同时开启执行权限和SUID、SGID、Sticky,则权限表示字符是小写的。

st_mode屏蔽
意义
S_IRUSR

S_IWUSR

S_IXUSR
用户-读

用户-写

用户-执行
S_IRGRP

S_IWGRP

S_IXGRP
组-读

组-写

组-执行
S_IROTH

S_IWOTH

S_IXOTH
其他-读

其他-写

其他-执行

3文件命令

3.1创建文件的命令

vi
filename

touch filename/*如果文件不存在,则创建空文件,否则更新文件的访问时间和修改时间*/

3.2删除文件

rm
–f filename

rm –f *

3.3复制文件

cp
source_file dest_file

mv
source_file dest

3.4查找文件

find
路径参数
表达式

通过遍历硬盘来查找。

名称查找参数:

-gidn
:寻找群组ID为n的文件

-group name :寻找群组名称为name的文件

-uid n :寻找拥有者ID为n的文件

-user name :寻找用户者名称为name的文件

-name file :寻找文件名为file的文件(可以使用通配符)

find [path] –name filename

其他

which
命令: shows thefull path of (shell) commands,查找可执行文件的位置

[root]# which sort

/bin/sort

[root]# which cc

/usr/bin/cc

[root]#

whereis命令:
locatethe binary, source, and manual page files for a command

查找应用程序名,且只能查找二进制文件(参数-b)、man说明文件(参数-m)和源代码文件(参数-s)。通过记录所有文件的数据库文件中查找,速度比较快。

[root]# whereis cc

cc: /usr/bin/cc

[root]# whereis -b sort

sort: /bin/sort

[root]#

locate命令:用于查找文件,相当于find–name的另一种写法,只是它搜索一个数据库/var/lib/mlocate/mlocate.db(ubuntu系统)。Locate可能看不到最新的文件,需要先手动更新数据库,即输入命令updatedb

[root]# locate yash.c

/tmp/unix/apue/yash.c

[root]#

4进程相关ID

实际用户ID

实际组ID
我们实际上是谁(在登录时取自口令文件中的登录项)
有效用户ID

有效组ID

附加组ID
用于文件访问权限检查
保存的设置用户ID

保存的设置组ID
由exec函数保存(在执行一个程序时包含了有效用户ID和有效组ID的副本)
进程每次打开、创建或删除一个文件时,内核就进行文件访问权限测试,而这种测试肯能涉及文件的所有者(st_uid和st_gid)、进程的有效ID(有效用户ID和有效组ID)以及进程的附加组ID(若支持的话)。两个所有者ID是文件的性质,而两个有效ID和附加组ID则是进程的性质。
当open函数打开一个文件时,内核以进程的有效用户ID和有效组ID为基础执行其访问权限测试。有时,进程也希望按其实际用户ID和实际组ID来测试访问能力。
access函数是按实际用户ID和实际组ID进行访问权限测试的。
#include <unistd.h>

int access(const char *pathname, int mode)

返回:成功返回0出错返回-1

参数:mode

mode是下列常量的按位或
mode
说明
R_OK

W_OK

X_OK

F_OK
测试读权限

测试写权限

测试执行权限

测试文件是否存在

5粘住位

对目录设置粘住位。
如果对一个目录设置了粘住位,则只有对该目录具有写权限的用户在满足下列条件之一
的情况下,才能删除或更名该目录下的文件:

拥有此文件

拥有此目录

是超级用户

目录/tmp和/var/spool/uucppublic是设置粘住位的典型候选者——任何用户都可以在这两个目录中创建文件。

6目录命令

6.1创建目录

mkdir

6.2删除目录

rmdif

rm -rf /dir

6.3改变目录

cd . //当前目录

cd .. //上级目录

6.4查看目录

pwd

7相关函数

1 umask函数:为进程设置文件模式创建屏蔽字

在进程创建一个新文件或新目录时,就一定会使用文件模式创建屏蔽字。对于任何在文件模式创建屏蔽字中为1的位,在文件mode中的相应位一定被关闭。
头文件
#include <sys/stat.h>
函数原型
mode_t umask(mode_t cmask);
参数
cmask:由S_IRUSR、S_IWUSR、S_IXUSR、S_IRGRP、S_IWGRP、S_IXGRP、S_IROTH、S_IWOTH、S_IXOTH等9个常量中的若干位按位“或”构成的。
返回
成功以前的文件模式创建屏蔽字
功能
为进程设置文件模式创建屏蔽字
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>

#define RWRWRW (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)

int main(void)
{
umask(0);
if (creat("foo", RWRWRW) < 0)
{
printf("create foo error\n");
return 1;
}

umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (creat("bar", RWRWRW) < 0)
{
printf("create bar error\n");
return 1;
}

return 0;
}


lincoln@ubuntu:~$ umask       打印当前文件模式创建屏蔽字
0022
<a target=_blank href="mailto:lincoln@ubuntu:~$">lincoln@ubuntu:~$</a> ./a.out
lincoln@ubuntu:~$ ls -l foo bar
-rw------- 1 lincoln lincoln 0 2015-06-07 16:25 bar
-rw-rw-rw- 1 lincoln lincoln 0 2015-06-07 16:25 foo
lincoln@ubuntu:~$ umask      系统默认的umask是0022
0022
<a target=_blank href="mailto:lincoln@ubuntu:~$">lincoln@ubuntu:~$</a> umask -S   打印符号形式
u=rwx,g=rx,o=rx
<a target=_blank href="mailto:lincoln@ubuntu:~$">lincoln@ubuntu:~$</a> umask 027  更改文件模式创建屏蔽字
<a target=_blank href="mailto:lincoln@ubuntu:~$">lincoln@ubuntu:~$</a> umask -S   打印符号形式
u=rwx,g=rx,o=
<a target=_blank href="mailto:lincoln@ubuntu:~$">lincoln@ubuntu:~$</a> umask 0022
lincoln@ubuntu:~$ umask -S
u=rwx,g=rx,o=rx
lincoln@ubuntu:~$

附:
在使用open或creat创建新文件时,文件的访问权限并非mode,而是(mode&~umask),其中umask是系统默认的文件模式创建屏蔽字的值,比如此处是0022,或者通过umask(cmask)函数修改的文件模式创建屏蔽字,即cmask的值。
更改进程的文件模式创建屏蔽字并不影响其父进程的文件模式创建屏蔽字。

2 chmod函数:更改文件访问权限

头文件
#include <sys/stat.h>
函数原型
int chmod(const char *pathname, mode_t mode);

int fchmod(int filedes, mode_t mode);
参数
pathname:文件名
mode参数
说明
S_ISUID

S_ISGID

S_ISVTX
执行时设置用户ID

执行时设置组ID

保存正文(粘住位)
S_IRWXU

S_IRUSR

S_IWUSR

S_IXUSR
用户读、写和执行

用户读

用户写

用户执行
S_IRWXG

S_IRGRP

S_IXGRP

S_IXGRP
组读、写和执行

组读

组写

组执行
S_IRWXO

S_IROTH

S_IWOTH

S_IXOTH
其他读、写和执行

其他读

其他写

其他执行
返回
成功返回0,出错返回-1
功能
chmod函数:在指定的文件上进行操作

fchmod函数:对已打开的文件进行操作

功能:更改现有文件的访问权限

3 chown函数:更改用户ID和组ID

头文件
#include <unistd.h>
函数原型
int chown(const char *pathname, uid_t owner, gid_t group);

int fchown(int filedes, uid_t owner, gid_t group);

int lchown(const char *pathname, uid_t owner, gid_t group);
参数
pathname:文件名

owner:用户ID

group:组ID
返回
成功返回0,出错返回-1
功能
三个函数均是更改文件的用户ID和组ID,其中lchown更改符号链接本身的所有者,而不是符号链接所指向的文件。

4 truncate函数:文件截短

头文件
#include <unistd.h>
函数原型
int truncate(const char *pathname, off_t length);

int ftruncate(int filedes, off_t length);
参数
pathname:文件名

length:文件截短后的长度,单位为字节
返回
成功返回0,出错返回-1
功能
在文件尾端截去一些数据以缩短文件,被截短的数据不能访问。

5 link函数:创建一个指向现有文件的链接(硬链接)

任何一个文件可以有多个目录项指向其i节点。每个i节点中都有一个链接计数,其值是指向该i节点的目录项数。只有当链接级数减少至0时,才可删除该文件(也就是可以释放该文件占用的数据块)。在stat结构中,链接计数包含在st_nlink成员中,其基本数据类型是nlink_t。这种链接类型称为硬链接。
头文件
#include <unistd.h>
函数原型
int link(const char *existingpath, const char *newpath);
参数
existingpath:现有的文件

newpath:新目录项
返回
成功返回0,出错返回-1
功能
创建一个指向现有文件的链接。即,创建一个新目录项newpath,它引用现有的文件existingpath。如若newpath已经存在,则返回出错。大多数实现要求这两个路径名在同一个文件系统中。(创建新目录项和增加链接计数应当是原子操作)
头文件
#include <unistd.h>
函数原型
int unlink(const char *pathname);
参数
pathname:文件名
返回
成功返回0,出错返回-1
功能
删除目录项,并将由pathname所引用文件的链接计数减1
头文件
#include <unistd.h>
函数原型
int remove(const char *pathname);
参数
pathname:文件名
返回
成功返回0,出错返回-1
功能
解除对一个文件或目录的链接。对于文件,remove的功能与unlink相同。对于目录,remove的功能与rmdir相同。

6 symlink函数:创建符号链接

符号链接是指向一个文件的间接指针,它与硬链接不同,硬链接直接指向文件的i节点。引入符号链接的原因是为了避开硬链接的一些限制:
1)硬链接通常要求链接和文件位于同一文件系统中。
2)只有超级用户才能创建指向目录的硬链接。
对符号链接以及它指向何种对象并无任何文件系统限制,任何用户都可创建指向目录的符号链接。符号链接一般用于将一个文件或整个目录结构移到系统中的另一个位置。
当使用以名字引用文件的函数时,需了解该函数是否处理符号链接。如若该函数具有处理符号链接的功能,则其路径名参数引用符号链接指向的文件;否则,路径名参数将引用链接本身。
即,需要了解该函数是否跟随符号链接到达它所链接的文件。
函数
不跟随符号链接
跟随符号链接
access

chdir

chmod

chown


creat

exec

lchown

link

lstat

open

opendir

pathconf

readlink

remove

rename

stat

truncate

unlink

头文件
#include <unistd.h>
函数原型
int symlink(const char *actualname, const char *sympath);
参数
actualname:文件名

sympath:新目录项
返回
成功返回0,出错返回-1
功能
创建一个符号链接。创建一个指向actualpath的新目录项sympath,在创建此符号链接时,并不要求actualpath已经存在。并且,actualpath和sympath并不需要位于同一文件系统中。
因为open函数跟随符号链接(即打开符号链接指向的文件),所以需要一种方法打开该链接本身,并读该链接中的名字。
头文件
#include <unistd.h>
函数原型
ssize_t readlink(const char *restrict pathname, char *restrict buf, size_t bufsize);
参数
pathname:文件名

buf:读数据的缓冲区

bufsize:读数据的大小
返回
成功返回读到的字节数,出错返回-1
功能
该函数组合了open、read和close的所有操作。在buf中返回的符号链接的内容不以NULL字符终止。

8 utime函数:更改文件的访问和修改时间

头文件
#include <utime.h>
函数原型
int utime(const char *pathname, const struct utimbuf *times);
参数
pathname:文件名

times:结构体指针

struct utimbuf{

time_t actime;/*最后访问时间*/

time_t modtime;/*最后修改时间*/

}
返回
成功返回0,出错返回-1
功能
用来更改文件的最后访问时间和最后修改时间

9 stat函数

头文件
#include <sys/stat.h>
函数原型
int stat(const char *restrict pathname, struct stat *restrict buf);

int fstat(int filedes, struct stat *buf);

int lstat(const char *restrict pathname, struct stat *restrict buf);
参数
pathname:文件名

buf:文件相关信息结构
返回
成功返回0,出错返回-1
功能
三个函数均是返回与文件有关的信息结构,其中lstat当文件是一个符号链接时,返回符号链接相关信息。

9 mkdir函数:创建目录

头文件
#include <sys/stat.h>
函数原型
int mkdir (const char *pathname, mode_t mode);
参数
pathname:文件名

mode:文件访问权限(由进程的文件模式创建屏蔽字修改)
返回
成功返回0,出错返回-1。(常见的错误是指定与文件相同的mode(只指定读、写权限,但是对于目录通常至少需要设置1个执行权限位,以允许访问该目录中的文件名))
功能
创建新目录,其中.和..目录是自动创建的。
头文件
#include <unistd.h>
函数原型
int rmdir (const char *pathname);
参数
pathname:文件名
返回
成功返回0,出错返回-1。
功能
删除一个空目录,空目录是只包含.和..这两项的目录。

10 chdir函数:更改当前工作目录

每个进程都有一个当前工作目录,此目录是搜索所有相对路径名的起点(不以斜杠开始的路径名为相对路径名)
头文件
#include <unistd.h>
函数原型
int chdir (const char *pathname);

int fchdir(int filedes);
参数
pathname:文件名
返回
成功返回0,出错返回-1。
功能
用pathname或打开文件描述符filedes指定新的当前工作目录


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