linux系统进程终止atexit函数 特殊权限s/t File结构体的信息内容

来源:互联网 发布:舞台交互制作软件 编辑:程序博客网 时间:2024/06/05 00:22

本文特殊权限s/t转载自:http://blog.csdn.net/kkdelta/article/details/7850669

FILE结构体信息转载自:http://blog.csdn.net/wangchaoxjtuse/article/details/6036684

进程终止
  进程终止的⽅方式有8种,前5种为正常终止,后三种为异常终止:
   1 从main函数返回;
   2 调用exit函数;
   3 调用_exit或_Exit;
   4 最后一个线程从启动例程返回;
   5 最后一个线程调⽤用pthread_exit;
   6 调用abort函数;
   7 接到一个信号并终⽌止;
   8 最后一个线程对取消请求做出响应。

(1)exit函数

函数格式:
  #include <stdlib.h>

  void exit( int status );
  void _Exit( int status );
  #include <unistd.h>
  void _exit( int status );
     这三个函数用于正常终止一个程序,_exit和_Exit立即进入内核,而exit则要先做一些清理工作(调用执行各终止处理程序,关闭所有标准I/O流),再进入内核。三个函数所带的整型参数称为终止状态或退出状态,如果(a)调用这些函数不带参数,(b)main函数中的return语句无返回值,(c)main函数没有声明返回类型为整型,则进程的终止状态是未定义的。main函数返回一个整型值与用该值调用exit是等价的。
(2)atexit函数
#include <stdlib.h>
int atexit( void (*fun)( void ) );
BIT

     atexit函数

函数格式:

   #include <stdlib.h>

   int atexit( void (*fun)( void ) );

功 能: 注册终止函数(即main执行结束后调用的函数)


实例1:atexit函数递归调用一个fun()函数


实例1结果:


由结果验证了atexit函数的功能在main函数结束后才回收进程


实例2:atexit函数分别递归调用函数fun1(),fun2(),fun3();


实例2结果:


由结果图我们知道atexit函数的调用顺序与声明注册顺序相反

特殊权限s/t

先看看这两个文件的权限:
[root@localhost ~]# ls -ld /usr/bin/passwd  /tmp
drwxrwxrwt 4 root root  4096 Jun  2 17:33 /tmp
-rwsr-xr-x 1 root root 22984 Jan  7  2007 /usr/bin/passwd

这里的s和t是针对执行权限来讲的。
个s权限,是为了让一般使用者临时具有该文件所属主/组的执行权限。就比如/usr/bin/passwd在执行它的时候需要去修改/etc/passwd和/etc/shadow等文件,这些文件除了root外,其他用户都没有写权限,但是又为了能让普通用户修改自己的密码,只能时临时让他们具有root的权限。所以这个s权限就是用来完成这个特殊任务的。s权限只能应用在二进制的可执行文件上。
如果你不想让普通用户修改自己的密码,只需要
[root@localhost ~]# chmod u-s /usr/bin/passwd  或者
[root@localhost ~]# chmod 0755 /usr/bin/passwd
0755最前面的0表示不使用任何特殊权限,该位上的数字可以是0,1(--t),2(-s-),3(-st),4(s--),5(s-t),6(ss-),7(sst)
那个t权限只针对目录生效,它表示只能让所属主以及root可以删除(重命名/移动)该目录下的文件。比如/tmp目录本来就是任何用户都可以读写,如果别人可以任意删除(重命名/移动)自己的文件,那岂不是很危险。所以这个t权限就是为了解决这个麻烦的。下面举一个例子,说明一下这个权限的用法:
[root@localhost ~]# cd /tmp/
[root@localhost tmp]# mkdir test
[root@localhost tmp]# chmod 1777 test
[root@localhost tmp]# ls -ld test
drwxrwxrwt 2 root root 4096 Jun  2 18:10 test
[root@localhost tmp]# su test1
[test1@localhost tmp]$ touch test/1.txt
[test1@localhost tmp]$ ls -l test
total 4
-rw-r--r-- 1 test1 test 0 Jun  2 18:12 1.txt
[test1@localhost tmp]$ exit
[root@localhost tmp]# su www
[www@localhost tmp]$ ls -l test/1.txt
-rwxrwxrwx 1 test1 test 6 Jun  2 18:12 test/1.txt
[www@localhost tmp]$ rm test/1.txt
rm: cannot remove `test/1.txt': Operation not permitted
提示不能删除1.txt
[www@localhost tmp]$ exit
[root@localhost tmp]# chmod -t test
去掉t权限。
[root@localhost tmp]# ls -ld test
drwxrwxrwx 2 root root 4096 Jun  2 18:13 test
[root@localhost tmp]# su www
[www@localhost tmp]$ rm -f test/1.txt
再次删除,则删除成功。
[www@localhost tmp]$ ls test/1.txt
ls: test/1.txt: No such file or directory

自己验证结果



FILE结构体:

struct file结构体定义在/Linux/include/linux/fs.h(Linux 2.6.11内核)中,其原型是:

代码:
struct file { 
  struct file *f_next,**f_pprev; 
  struct dentry *f_dentry; 
  struct file_operations *f_op; 
  mode_t f_mode; 
  loff_t f_pos; 
  unsigned int f_count,f_flags; 
  unsigned long f_reada,f_ramax,f_raend,f_ralen,f_rawin; 
  struct fown_struct f_owner; 
  unsigned long f_version; 
  void *private_data; 
  };
struct file {        /*         * fu_list becomes invalid after file_free is called and queued via         * fu_rcuhead for RCU freeing         */        union {                struct list_head        fu_list;                struct rcu_head         fu_rcuhead;        } f_u;        struct path             f_path;#define f_dentry        f_path.dentry#define f_vfsmnt        f_path.mnt        const struct file_operations    *f_op;        atomic_t                f_count;        unsigned int            f_flags;        mode_t                  f_mode;        loff_t                  f_pos;        struct fown_struct      f_owner;        unsigned int            f_uid, f_gid;        struct file_ra_state    f_ra;        unsigned long           f_version;#ifdef CONFIG_SECURITY        void                    *f_security;#endif        /* needed for tty driver, and maybe others */        void                    *private_data;#ifdef CONFIG_EPOLL        /* Used by fs/eventpoll.c to link all the hooks to this file */        struct list_head        f_ep_links;        spinlock_t              f_ep_lock;#endif /* #ifdef CONFIG_EPOLL */        struct address_space    *f_mapping;};
文件结构体代表一个打开的文件,系统中的每个打开的文件在内核空间都有一个关联的struct file。它由内核在打开文件时创建,并传递给在文件上进行操作的任何函数。在文件的所有实例都关闭后,内核释放这个数据结构。在内核创建和驱动源码中,struct file的指针通常被命名为file或filp。一下是对结构中的每个数据成员的解释:
一、
union {
    struct list_head fu_list;
    struct rcu_head rcuhead;
}f_u;
其中的struct list_head定义在 linux/include/linux/list.h中,原型为:
struct list_head {
        struct list_head *next, *prev;
};
用于通用文件对象链表的指针。
struct rcu_head定义在linux/include/linux/rcupdate.h中,其原型为:
/*** struct rcu_head - callback structure for use with RCU* @next: next update requests in a list* @func: actual update function to call after the grace period.*/struct rcu_head {        struct rcu_head *next;        void (*func)(struct rcu_head *head);};
RCU(Read-Copy Update)是Linux 2.6内核中新的锁机制,具体在这里有介绍:
http://www.ibm.com/developerworks/cn/linux/l-rcu/
二、
struct path             f_path;
被定义在linux/include/linux/namei.h中,其原型为:
struct path {
        struct vfsmount *mnt;
        struct dentry *dentry;
};
在早些版本的内核中并没有此结构,而是直接将path的两个数据成员作为struct file的数据成员,
struct vfsmount *mnt的作用是指出该文件的已安装的文件系统,
struct dentry *dentry是与文件相关的目录项对象。
三、
const struct file_operations    *f_op;
被定义在linux/include/linux/fs.h中,其中包含着与文件关联的操作,如:
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
等。当打开一个文件时,内核就创建一个与该文件相关联的struct file结构,其中的*f_op就指向的是
具体对该文件进行操作的函数。例如用户调用系统调用read来读取该文件的内容时,那么系统调用read最终会陷入内核调用sys_read函数,而sys_read最终会调用于该文件关联的struct file结构中的f_op->read函数对文件内容进行读取。
四、
atomic_t                f_count;
atomic_t被定义为:
typedef struct { volatile int counter; } atomic_t;
volatile修饰字段告诉gcc不要对该类型的数据做优化处理,对它的访问都是对内存的访问,而不是对寄存器的访问。 
本质是int类型,之所以这样写是让编译器对基于该类型变量的操作进行严格的类型检查。此处f_count的作用是记录对文件对象的引用计数,也即当前有多少个进程在使用该文件。
五、
unsigned int            f_flags;
当打开文件时指定的标志,对应系统调用open的int flags参数。驱动程序为了支持非阻塞型操作需要检查这个标志。
六、
mode_t                  f_mode;
对文件的读写模式,对应系统调用open的mod_t mode参数。如果驱动程序需要这个值,可以直接读取这个字段。
mod_t被定义为:
typedef unsigned int __kernel_mode_t;
typedef __kernel_mode_t         mode_t;
七、
loff_t                  f_pos;
当前的文件指针位置,即文件的读写位置。
loff_t被定义为:
typedef long long       __kernel_loff_t;
typedef __kernel_loff_t         loff_t;
八、
struct fown_struct      f_owner;struct fown_struct在linux/include/linux/fs.h被定义,原型为:struct fown_struct {        rwlock_t lock;          /* protects pid, uid, euid fields */        struct pid *pid;        /* pid or -pgrp where SIGIO should be sent */        enum pid_type pid_type; /* Kind of process group SIGIO should be sent to */        uid_t uid, euid;        /* uid/euid of process setting the owner */        int signum;             /* posix.1b rt signal to be delivered on IO */};
该结构的作用是通过信号进行I/O时间通知的数据。
九、
unsigned int            f_uid, f_gid;
标识文件的所有者id,所有者所在组的id.
十、
struct file_ra_state    f_ra;
struct file_ra_state结构被定义在/linux/include/linux/fs.h中,原型为:
struct file_ra_state {        pgoff_t start;                  /* where readahead started */        unsigned long size;             /* # of readahead pages */        unsigned long async_size;       /* do asynchronous readahead when                                           there are only # of pages ahead */                                                   unsigned long ra_pages;         /* Maximum readahead window */        unsigned long mmap_hit;         /* Cache hit stat for mmap accesses */        unsigned long mmap_miss;        /* Cache miss stat for mmap accesses */        unsigned long prev_index;       /* Cache last read() position */        unsigned int prev_offset;       /* Offset where last read() ended in a page */};
文件预读状态,文件预读算法使用的主要数据结构,当打开一个文件时,f_ra中出了perv_page(默认为-1)和ra_apges(对该文件允许的最大预读量)这两个字段外,其他的所有西端都置为0。
十一、
unsigned long           f_version;
记录文件的版本号,每次使用后都自动递增。
十二、
#ifdef CONFIG_SECURITY
        void                    *f_security;
#endif
此处我的理解是如果在编译内核时配置了安全措施,那么struct file结构中就会有void *f_security数据项,用来描述安全措施或者是记录与安全有关的信息。
十三、
void *private_data;
系统在调用驱动程序的open方法前将这个指针置为NULL。驱动程序可以将这个字段用于任意目的,也可以忽略这个字段。驱动程序可以用这个字段指向已分配的数据,但是一定要在内核释放file结构前的release方法中清除它。
十四、
#ifdef CONFIG_EPOLL
        /* Used by fs/eventpoll.c to link all the hooks to this file */
        struct list_head        f_ep_links;
        spinlock_t              f_ep_lock;
#endif /* #ifdef CONFIG_EPOLL */
被用在fs/eventpoll.c来链接所有钩到这个文件上。其中f_ep_links是文件的事件轮询等待者链表的头,f_ep_lock是保护f_ep_links链表的自旋锁。
十五、struct address_space    *f_mapping;
struct address_space被定义在/linux/include/linux/fs.h中,此处是指向文件地址空间的指针。
  在驱动开发中,文件读/写模式mode、标志f_flags都是设备驱动关心的内容,而私有数据指针private_data在折本驱动中被广泛使用,大多被指向设备驱动自定义用于描述设备的结构体。 
驱动程序中常用如下类似的代码来检测用户打开文件的读写方式:
if (file->f_mode & FMODE_WRITE) //用户要求可写
  {
  }
  if (file->f_mode & FMODE_READ) //用户要求可读
  {
  }
下面的代码可用于判断以阻塞还是非阻塞方式打开设备文件:
  if (file->f_flags & O_NONBLOCK) //非阻塞
      pr_debug("open:non-blocking/n");
  else //阻塞
      pr_debug("open:blocking/n");




0 0