《unix环境高级编程》 读书笔记 (2)

目录: http://blog.csdn.net/alex_my/article/details/39346381

Files and Directories


1 stat, fstat, lstat, fstatat

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int stat(const char *path, struct stat *buf);

int lstat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);

stat: 根据path路径,获取信息。

lstat: 功能和stat类似,但如果path指向的是一个符号链接(软链接),返回的是该符号链接的信息,而不是其所指向的文件信息。

fstat: 功能和stat类似,第一参数为文件描述符。

#include <fcntl.h> /* Definition of AT_* constants */

#include <sys/stat.h>

int fstatat(int dirfd, const char *pathname, struct stat *buf, int flags);

-1: 如果pathname是相对路径,则是相对于dirfd的路径,不是相对于当前进程工作空间。

-2: 如果pathname是相对路径,且dirfd为AT_FDCWD,则是相对于当前进程工作空间。

-3: 如果pathname是绝对路径,则dirfd会被忽略。

第四个参数flags可以取以下值:

AT_EMPTY_PATH: pathname可以为空,此时获得的是dirfd所指向文件的信息。

AT_NO_AUTOMOUNT: 和挂载点有关,允许手机挂载点的属性。

AT_SYMLINK_NOFOLLOW: 如果path指向一个符号链接,则返回该链接信息。默认情况下,fstatat返回的就是链接信息。

补充:

软链接,硬链接信息可以参考这里:

http://www.cnblogs.com/stli/archive/2010/11/10/1873212.html


2 File Types

regular file: 普通文件,当我们使用ls -l查看的时候,会出现例如-rw-rw-r--, 第一个符号是'-'。

directory file: 目录文件,比较特殊的文件,存放着文件名和文件索引结点之间的关联。

block special file: 提供固定大小传送数据,包括磁盘驱动,光盘驱动。

character device: 以字节流传送数据,包括终端设备和串口设备。

fifo: 也成pipe,方便进程之间通信。

socket: 方便进程之间通信,进程可以分步在不同的计算机上。

symbolic link: 符号链接,软链接。

以上可以通过传入stat结构体中的st_mode来辨认类型:

S_ISREG()

S_ISDIR()

S_ISCHR()

S_ISBLK()

S_ISFIFO()

S_ISLNK()

S_ISSOCK()

另外,还提供stat结构体指针来辨认以下类型:

S_TYPEISMQ()      : 消息队列

S_TYPEISSEM()     : 信号

S_TYPEISSHM()     : 共享内存对象

程序用例:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string>

int main(int argc, char* argv[])
{
     struct stat buff;
     std::string ptr;

     for(int i = 0; i < argc; ++i)
     {
          printf("%s: ", argv[i]);

          if(lstat(argv[i], &buff) == -1)
          {
               printf("error[%s]\n", argv[i]);
               continue;
          }

          if(S_ISREG(buff.st_mode))
               ptr = "regular";
          else if(S_ISDIR(buff.st_mode))
               ptr = "directory";
          else if(S_ISCHR(buff.st_mode))
               ptr = "character special";
          else if(S_ISBLK(buff.st_mode))
               ptr = "block special";
          else if(S_ISLNK(buff.st_mode))
               ptr = "symbolic link";
          else if(S_ISSOCK(buff.st_mode))
               ptr = "socket";
          else if(S_TYPEISMQ(&buff))
               ptr = "queue message";
          else if(S_TYPEISSEM(&buff))
               ptr = "semahore";
          else if(S_TYPEISSHM(&buff))
               ptr = "shared memory object";
          else
               ptr = "unknown mode";

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

     return 0;
}


3 real user ID/ effective user ID/ saved set-user-ID

real user ID 即进程调用者是谁,在登陆的时候就获得的值。

effective user ID 用来校验该进程执行时获得的文件访问权限,也就是当进程访问文件的时候,权限检查的时候检查的是这个值。

saved set-user-ID 在某种情况下保存effective user ID副本。

如果没有进行处理,real user ID 与effective user ID是相同的。

更多内容在8.11章涉及,日后补上。

可以先参考这里:

http://www.cppblog.com/converse/archive/2007/12/20/39166.html


4 access faccessat

 #include <unistd.h>

 int access(const char *pathname, int mode);

 #include <unistd.h>
 #include <fcntl.h>

 int faccessat(int dirfd, const char *pathname, int mode, int flags);

 access: 检测进程对文件的操作权限

 faccessat: 检测目录下文件的操作权限

 mode可以取以下值:

 F_OK: 文件是否存在

 

 R_OK, W_OK, X_OK,这三个可以通过or的方式结合。

 对于faccessat,dirfd和pathname之间的关系可以参考本文fstatat中的说明。

 flags可以取以下值:

 AT_EACCESS: 执行检测的时候,检测effective user/group ID,默认检测的是real ID

 

 AT_SYMLINK_NOFOLLOW: 如果检测的目标是一个符号链接(symbolic link),检测进程对该链接的操作权限,而不是其所指向的文件的操作权限。no follow,别跟过去。

 程序用例:

 // test4.8.cc

 

 #include <stdio.h>
 #include <unistd.h>

 int main(int argc, char* argv[])
 {
      if(argc != 2)
      {
           printf("error 1\n");
           return 1;
      }

      if(access(argv[1], F_OK) < 0)
           printf("file[%s] is not exist\n", argv[1]);
    
      if(access(argv[1], R_OK) < 0)
           printf("file[%s] is not readable\n", argv[1]);
      else
           printf("file[%s] is readable\n", argv[1]);

      return 0;
 }

 

 // 普通用户

 g++ -o test4.8 test4.8.cc

 

 ./test4.8 /etc/passwd   ---> file[/etc/passwd] is readable

 

 ./test4.8 /etc/shadow   ---> file[/etc/shadow] is not readable


5 改变文件的操作权限

 #include <sys/stat.h>

 int chmod(const char *path, mode_t mode);
 int fchmod(int fd, mode_t mode);

 

 #include <fcntl.h>           /* Definition of AT_* constants */
 #include <sys/stat.h>

 int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags);

 在进行以上操作的时候, effective user ID必须和文件的owner ID相同,或者拥有超级权限。

 mode可选的值有:

 S_ISUID  (04000)  set-user-ID  

 S_ISGID  (02000)  set-group-ID 

 S_ISVTX  (01000)  sticky bit

 S_IRWXU  (00700)  read, write, execute by owner

      S_IRUSR  (00400)  read by owner

      S_IWUSR  (00200)  write by owner

      S_IXUSR  (00100)  execute/search  by owner 

 S_IRWXG  (00070)  read, write, execute by group

      S_IRGRP  (00040)  read by group

      S_IWGRP  (00020)  write by group

      S_IXGRP  (00010)  execute/search by group

 S_IRWXO  (00007)  read, write, execute by others

      S_IROTH  (00004)  read by others

      S_IWOTH  (00002)  write by others

      S_IXOTH  (00001)  execute/search by others

 上一个程序用例中生成的可执行文件test4.8,使用ls -l查看:

 -rwxrwxr-x.

 

 程序用例:

 #include <stdio.h>

 #include <unistd.h>
 #include <sys/stat.h>

 int main(int argc, char* argv[])
 {
      struct stat statBuff;
 
      if(stat("test4.8", &statBuff) < 0)
      {
           printf("error 1\n");
           return 1;
      }

      if(chmod("test4.8", (statBuff.st_mode | S_IRWXO)) < 0)
      {
           printf("error 2\n");
           return 1;
      }

      return 0;
 }

 执行完test4.9后,ls -l查看test4.8:

 -rwxrwxrwx.


6 holes in a file

有时候会分配一个固定大小的文件,但是并不立即往其中写入数据。如果为这部分暂时不写如数据的部分分配磁盘空间,就有些浪费了。为了解决这个问题,引入了文件洞的概念,普通文件中包含空字符的那部分,在磁盘上并不会使用任何空间来保存,只有当真正为该文件写入数据时,才真正的为该文件分配数据块。 


7 file truncation

#include <unistd.h>
#include <sys/types.h>

int truncate(const char *path, off_t length);
int ftruncate(int fd, off_t length);

使文件按指定长度截断, 如果长度增大,则在这之间补充0,或者是产生file hole

在open一个文件使用的标识符:O_TRUNC是一个截断的特例。


8 creating and read symbolic link

 #include <unistd.h>

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

 int symlinkat(const char *oldpath, int newdirfd, const char *newpath);

 #include <unistd.h>

 ssize_t readlink(const char *path, char *buf, size_t bufsiz);

 int readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz);


参考:

http://www.cnblogs.com/stli/archive/2010/11/10/1873212.html

http://www.cppblog.com/converse/archive/2007/12/20/39166.html

时间: 2024-08-24 03:33:09

《unix环境高级编程》 读书笔记 (2)的相关文章

UNIX环境高级编程中的apue.h

/************** * *apueerror.h * *************/ #include <apue.h> #include <stdio.h> #include <errno.h> /* for definition of errno */ #include <stdarg.h> /* ISO C variable aruments */ static void err_doit(int, int, const char *, va

unix高级编程-UNIX环境高级编程 times() 疑问

问题描述 UNIX环境高级编程 times() 疑问 例程 int main(int argc, char *argv[]) { clock_t s_clk,e_clk; struct tms s_tms,e_tms; s_clk = times(&s_tms); system("ls /dev"); system("date"); sleep(1); e_clk = times(&e_tms); printf("e_clk %ld - s

ubuntu-最近在学习Unix 环境高级编程,配置环境时遇到了些问题

问题描述 最近在学习Unix 环境高级编程,配置环境时遇到了些问题 最近再看APUE(UNix 环境高级编程)的第三版,照着教程在中配置环境.也就是想要运行书中的源码,则要安装 libbsd-dev包,而每次安装这个包时,都如上报错,请问各位大虾,该怎么解决呢? 解决方案 你好, 类似的问题我也遇到过 ubuntu下apt-get install安装软件, 报"无法修正错误,因为您要求某些软件包保持现状,就是它们破坏了软件包间的依赖关系",今天终于找到解决方法了. 一般出现这种情况的原

unix环境高级编程-UNIX环境高级编程源代码对应

问题描述 UNIX环境高级编程源代码对应 今天开始学习UNIX环境高级编程,书中的源代码下载到了,但是发现根本不是按章节来的,找起来是相当的费时间,有哪位大神用过后知道他们的对应关系么,比如1-1对应ls1.c这样,真是万分感激,造福大家啊!

Mac OS X 10.8 中编译APUE(Unix环境高级编程)的源代码过程_C 语言

最近在温习APUE(<unix环境高级编程>),以前都是在linux下搞,现在打算在自己机器弄下,于是google了下,把编译的事情搞定了,修改了一些教程的一些错误,比如下载链接之类的. 1.下载源文件,我这里是第二版,貌似第三版的英文版出来了... 复制代码 代码如下: wget http://www.apuebook.com/src.2e.tar.gz 2.解压 复制代码 代码如下: tar zxf src.2e.tar.gz 3.修改些东西 复制代码 代码如下: cd apue.2e/

UNIX环境高级编程---标准I/O库

前言:我想大家学习C语言接触过的第一个函数应该是printf,但是我们真正理解它了吗?最近看Linux以及网络编程这块,我觉得I/O这块很难理解.以前从来没认识到Unix I/O和C标准库I/O函数压根不是一码事.Unix I/O也叫低级I/O,也叫Unbuffered I/O,是操作系统内核部分,也是系统调用:而C标准I/O函数相对也成Buffered I/O,高级I/O,一般是为了效率考虑对这些系统调用的封装.以前使用getchar()经常为输入完后的回车而出错.那是不理解标准I/O实现时的

UNIX环境高级编程:线程同步之互斥锁、读写锁和条件变量

一.使用互斥锁 1.初始化互斥量 pthread_mutex_t mutex =PTHREAD_MUTEX_INITIALIZER;//静态初始化互斥量 int pthread_mutex_init(pthread_mutex_t*mutex,pthread_mutexattr_t*attr);//动态初始化互斥量 int pthread_mutex_destory(pthread_mutex_t*mutex);//撤销互斥量 不能拷贝互斥量变量,但可以拷贝指向互斥量的指针,这样就可以使多个函数

UNIX环境高级编程:线程属性

pthread_attr_t 的缺省属性值 1.初始化一个线程对象的属性 int pthread_attr_init(pthread_attr_t *attr); 返回值:若是成功返回0,否则返回错误的编号 形  参: attr       指向一个线程属性的指针 说  明:Posix线程中的线程属性pthread_attr_t主要包括scope属性.detach属性.堆栈地址.堆栈大小.优先级. pthread_attr_init实现时为属性对象分配了动态内存空间. 线程属性结构如下: typ

UNIX环境高级编程:线程属性之并发度

并发度控制着用户级线程可以映射的内核线程或进程的数目.如果操作系统的实现在内核级的线程和用户级的线程之间保持一对一的映射,那么改变并发度并不会有什么效果,因为所有的用户级线程都可能被调度到.但是,如果操作系统的实现让用户级线程到内核级线程或进程之间的映射关系是多对一的话,那么在给定时间内增加可运行的用户级线程数,可能会改善性能. pthread_setconcurrency函数可以用于提示系统,表明希望的并发度. #include <pthread.h> int pthread_getconc

UNIX环境高级编程:system V消息队列

unix早期通信机制中的信号能够传送的信息量有限,管道则只能传送无格式字节流,这远远是不够的. 消息队列(也叫报文队列)客服了这些缺点: 消息队列就是一个消息的链表. 可以把消息看作一个记录,具有特定的格式. 进程可以按照一定的规则向消息队列中添加新消息:另一些进程可以从消息队列中读走消息. 消息队列是随内核持续的,只有内核重启或人工删除时,该消息队列才会被删除. system V消息队列使用消息队列标识符标识.具有足够特权的任何进程都可以往一个给定队列放置一个消息,具有足够特权的任何进程都可以