粘滞位 File文件内容

t权限(粘滞位):

是‘不可删除’权限,就是说即使某用户拥有这个文件的rwx权限,可以随意修改文件内容,但是就是不能删除,甚至不能修改文件名,只有root才行。t权限也可以直接用 chmod  o+t/a+t  filename 和chmod -t filename 来修改。

只针对目录生效,它表示只能让所属主以及root可以删除(重命名/移动)该目录下的文件。比如/tmp目录本来就是任何用户都可以读写,如果别人可以任意删除(重命名/移动)自己的文件,那岂不是很危险,所以这个t权限就是为了解决这个问题。

下面通过一个实例来体会这个t权限的用法:

(1) root用户在/tmp目录下创建一个test目录,并设置test目录的相关权限为1777(有特殊权限t)

[root@localhost tmp]# mkdir test
[root@localhost tmp]# chmod1777 test
[root@localhost tmp]# ls -ld test
drwxrwxrwt. 2 root root 4096 Oct 1222:31 test

(2) 切换到第一个用户zhangming,在test目录下创建一个新文件aaa.txt,并写入数据

[root@localhost tmp]# su zhangming
[zhangming@localhost tmp]$ touch test/aaa.txt
[zhangming@localhost tmp]$ echo"hello" >> test/aaa.txt
[zhangming@localhost tmp]$ ls -l test
total 4
-rw-rw-r--. 1 zhangming zhangming 6 Oct 1222:34 aaa.txt

(3) 切换到第二个用户shuihuo379,尝试删除zhangming用户创建的文件aaa.txt,此时提示无法删除

[zhangming@localhost tmp]$ su shuihuo379
[shuihuo379@localhost tmp]$ ls -l test/aaa.txt-rw-rw-r--. 1 zhangming zhangming 6 Oct 1222:34 test/aaa.txt
[shuihuo379@localhost tmp]$ rm test/aaa.txtrm: remove write-protected regular file `test/aaa.txt'? yrm: cannot remove `test/aaa.txt': Operation not permitted

(4) 重新切换到root用户,执行删除权限位t操作

[shuihuo379@localhost tmp]$ su
[root@localhost tmp]# chmod -t test
[root@localhost tmp]# ls -ld test
drwxrwxrwx. 2 root root 4096 Oct 1222:33 test

(5) 再次切换到用户shuihuo379,尝试删除zhangming用户创建的文件aaa.txt,此时删除成功,zhangming用户创建的文件aaa.txt已经不存在了

[root@localhost tmp]# su shuihuo379
[shuihuo379@localhost tmp]$ ls -l test
total 4
-rw-rw-r--. 1 zhangming zhangming 6 Oct 1222:34 aaa.txt
[shuihuo379@localhost tmp]$ rm test/aaa.txtrm: remove write-protected regular file `test/aaa.txt'? y
[shuihuo379@localhost tmp]$ ls -l test
total 0

粘滞位(粘着位)

上面所说的t权限就是我们在这里要讲的粘滞位(sticky bit),我们给刚刚的cur目录采用chmod o+t的方式给other用户设置粘滞位。


然后我们继续切换到dh用户,看看我们能否继续之前的删除操作:


可以看到此时我们是没有权限删除root用户创建的文件了,这也就是粘滞位的作用。

粘滞位权限便是针对此种情况设置,当录被设置了粘滞位权限以后,即便户对该录有写权限,也不能删除该录中其他户的件数据,是只有该件的所有者和root户才有权将其删除。设置了粘滞位之后,正好可以保持种动态的平衡:允许各户在录中任意写、删除数据,但是禁随意删除其他户的数据。

几点说明

对于特殊权限的添加是添加在原有的执行权限上的,所以特殊权限添加的要求需要文件或者目录本身具有可执行权限。

上图中,我去掉了cur的other的执行权限,可以看到本来't'的位置变成了'T',此时dh用户在cur目录中是不具有权限来进行一系列操作的。

那么原来的执行标志x到哪里去了呢? 系统是这样规定的, 假如本来在该位上有x, 则这些特别标志 (suid, sgid, sticky) 显示为小写字母 (s, s, t).否则, 显示为大写字母 (S, S, T) 。  

注意事项

粘滞位权限是针对目录的,对文件无效


上述的这些操作是在root用户下创建了一个test.c文件,然后添加了t权限,然而在dh用户下还是可以直接进行删除的。所以粘滞位是针对有执行权限的目录的,对于文件添加粘滞位并没有什么作用。

2.粘滞位权限(sticky)

作用:设置粘滞位权限后,即便用户和对目录有写入权限,也不能删除该目录中其他用户的文件

应用场景:对于公共可写目录,用户可创建删除自己的文件,但是不能删除其他用户的文件

表现形式:sticky表示为文件其它用户执行权限位上的t或T:

x: t -:T

若之前在其它用户执行位已有执行权限,则显示为t,否则显示为T

使用,如chmod o+t filename ...

chmodo-t filename ...

数字1表示增加粘滞位权限;数字0表示取消粘滞位权限;

使用,如:chmod 1755 filename ...

 

实例演示:(以上一次操作为前提)

(1)对/tmp/dirtest/设置粘滞位权限

1.[root@Liu ~]# chmod o+t /tmp/dirtest/

2.[root@Liu ~]# ll -d /tmp/dirtest/

3.drwxrwxr-t 2 root cloud 4096 Mar 1202:58 /tmp/dirtest/

 

(2)测试用户是否能删除非自己创建的文件

1.[docker@Liu dirtest]$touch docker.txt

2.[docker@Liu dirtest]$rm -rfopenstack.txt

3.rm: cannot remove `openstack.txt':Operation not permitted

4.[openstack@Liu dirtest]$touch openstack.txt

5.[openstack@Liu dirtest]$rm -rfdocker.txt

6.rm: cannot remove `docker.txt':Operation not permitted

答案是否定的。

这样的话,用户可以在此目录中随意创建文件和目录,但是不能删除非自己创建的文件或目录

 

所以,最终解决方案是:

1.[root@Liu ~]# useradd openstack

2.[root@Liu ~]# useradd docker

3.[root@Liu ~]# groupadd cloud

4.[root@Liu ~]# gpasswd  -Mopenstack,docker cloud

5.[root@Liu ~]# chmod g+w /tmp/test/

6.[root@Liu ~]# chown .cloud/tmp/test

7.[root@Liu ~]# chmod g+s /tmp/test/

8.[root@Liu ~]# chmod o+t /tmp/test/

这样,openstack和docker用户都可以git目录中创建文件,修改自己以及对方的文件,但是不能删除对方的文件。如果连对方的文件都不允许修改,只要chmod g-s /tmp/test即可。

 

File_struct:

在具体介绍这几个结构以前,我们需要解释一下文件描述符、打开的文件描述、系统打开文件表、用户打开文件表的概念以及它们的联系。

1.文件对象

Linux中,进程是通过文件描述符(file descriptors,简称fd)而不是文件名来访问文件的,文件描述符实际上是一个整数。Linux中规定每个进程能最多能同时使用NR_OPEN个文件描述符,这个值在fs.h中定义,为1024*1024(2.0版中仅定义为256)。

每个文件都有一个32位的数字来表示下一个读写的字节位置,这个数字叫做文件位置。每次打开一个文件,除非明确要求,否则文件位置都被置为0,即文件的开始处,此后的读或写操作都将从文件的开始处执行,但你可以通过执行系统调用LSEEK(随机存储)对这个文件位置进行修改。Linux中专门用了一个数据结构file来保存打开文件的文件位置,这个结构称为打开的文件描述(openfile description)。这个数据结构的设置是煞费苦心的,因为它与进程的联系非常紧密,可以说这是VFS中一个比较难于理解的数据结构。

首先,为什么不把文件位置干脆存放在索引节点中,而要多此一举,设一个新的数据结构呢?我们知道,Linux中的文件是能够共享的,假如把文件位置存放在索引节点中,则如果有两个或更多个进程同时打开同一个文件时,它们将去访问同一个索引节点,于是一个进程的LSEEK操作将影响到另一个进程的读操作,这显然是不允许也是不可想象的。

另一个想法是既然进程是通过文件描述符访问文件的,为什么不用一个与文件描述符数组相平行的数组来保存每个打开文件的文件位置?这个想法也是不能实现的,原因就在于在生成一个新进程时,子进程要共享父进程的所有信息,包括文件描述符数组。

我们知道,一个文件不仅可以被不同的进程分别打开,而且也可以被同一个进程先后多次打开。一个进程如果先后多次打开同一个文件,则每一次打开都要分配一个新的文件描述符,并且指向一个新的file结构,尽管它们都指向同一个索引节点,但是,如果一个子进程不和父进程共享同一个file结构,而是也如上面一样,分配一个新的file结构,会出现什么情况了?让我们来看一个例子:

假设有一个输出重定位到某文件A的shellscript(shell脚本),我们知道,shell是作为一个进程运行的,当它生成第一个子进程时,将以0作为A的文件位置开始输出,假设输出了2K的数据,则现在文件位置为2K。然后,shell继续读取脚本,生成另一个子进程,它要共享shell的file结构,也就是共享文件位置,所以第二个进程的文件位置是2K,将接着第一个进程输出内容的后面输出。如果shell不和子进程共享文件位置,则第二个进程就有可能重写第一个进程的输出了,这显然不是希望得到的结果。

至此,已经可以看出设置file结构的原因所在了。

file结构中主要保存了文件位置,此外,还把指向该文件索引节点的指针也放在其中。file结构形成一个双链表,称为系统打开文件表,其最大长度是NR_FILE,在fs.h中定义为8192。

file结构在include\linux\fs.h中定义如下:

structfile

{

struct list_head f_list; /*所有打开的文件形成一个链表*/

struct dentry *f_dentry; /*指向相关目录项的指针*/

struct vfsmount *f_vfsmnt; /*指向VFS安装点的指针*/

structfile_operations *f_op; /*指向文件操作表的指针*/

mode_tf_mode; /*文件的打开模式*/

loff_tf_pos; /*文件的当前位置*/

unsignedshort f_flags; /*打开文件时所指定的标志*/

unsignedshort f_count; /*使用该结构的进程数*/

unsignedlong f_reada, f_ramax, f_raend, f_ralen, f_rawin;

/*预读标志、要预读的最多页面数、上次预读后的文件指针、预读的字节数以及

预读的页面数*/

intf_owner; /* 通过信号进行异步I/O数据的传送*/

unsignedint f_uid, f_gid; /*用户的UID和GID*/

intf_error; /*网络写操作的错误码*/

unsignedlong f_version; /*版本号*/

void*private_data; /* tty驱动程序所需 */

};

每个文件对象总是包含在下列的一个双向循环链表之中:

·“未使用”文件对象的链表。该链表既可以用做文件对象的内存高速缓存,又可以当作超级用户的备用存储器,也就是说,即使系统的动态内存用完,也允许超级用户打开文件。由于这些对象是未使用的,它们的f_count域是NULL,该链表首元素的地址存放在变量free_list中,内核必须确认该链表总是至少包含NR_RESERVED_FILES个对象,通常该值设为10。

·“正在使用”文件对的象链表:该链表中的每个元素至少由一个进程使用,因此,各个元素的f_count域不会为NULL,该链表中第一个元素的地址存放在变量anon_list中。

如果VFS需要分配一个新的文件对象,就调用函数get_empty_filp()。该函数检测“未使用”文件对象链表的元素个数是否多于NR_RESERVED_FILES,如果是,可以为新打开的文件使用其中的一个元素;如果没有,则退回到正常的内存分配。

2.用户打开文件表

每个进程用一个files_struct结构来记录文件描述符的使用情况,这个files_struct结构称为用户打开文件表,它是进程的私有数据。files_struct结构在include/linux/sched.h中定义如下:

struct files_struct {

atomic_tcount; /* 共享该表的进程数 */

rwlock_t file_lock; /* 保护以下的所有域,以免在tsk->alloc_lock中的嵌套*/

intmax_fds; /*当前文件对象的最大数*/

intmax_fdset; /*当前文件描述符的最大数*/

intnext_fd; /*已分配的文件描述符加1*/

structfile ** fd; /* 指向文件对象指针数组的指针 */

fd_set*close_on_exec; /*指向执行exec( )时需要关闭的文件描述符*/

fd_set*open_fds; /*指向打开文件描述符的指针*/

fd_setclose_on_exec_init;/* 执行exec( )时需要关闭的文件描述符的初 值集合*/

       fd_set open_fds_init; /*文件描述符的初值集合*/

structfile * fd_array[32];/* 文件对象指针的初始化数组*/

};

fd域指向文件对象的指针数组。该数组的长度存放在max_fds域中。通常,fd域指向files_struct结构的fd_array域,该域包括32个文件对象指针。如果进程打开的文件数目多于32,内核就分配一个新的、更大的文件指针数组,并将其地址存放在fd域中;内核同时也更新max_fds域的值。

对于在fd数组中有入口地址的每个文件来说,数组的索引就是文件描述符(file descriptor)。通常,数组的第一个元素(索引为0)是进程的标准输入文件,数组的第二个元素(索引为1)是进程的标准输出文件,数组的第三个元素(索引为2)是进程的标准错误文件(参见图8.3)。请注意,借助于dup( )、dup2( )和 fcntl( )系统调用,两个文件描述符就可以指向同一个打开的文件,也就是说,数组的两个元素可能指向同一个文件对象。当用户使用shell结构(如2>&1)将标准错误文件重定向到标准输出文件上时,用户总能看到这一点。

open_fds域包含open_fds_init域的地址,open_fds_init域表示当前已打开文件的文件描述符的位图。max_fdset域存放位图中的位数。由于数据结构fd_set有1024位,通常不需要扩大位图的大小。不过,如果确实必须的话,内核仍能动态增加位图的大小,这非常类似文件对象的数组的情形。

当开始使用一个文件对象时调用内核提供的fget()函数。这个函数接收文件描述符fd作为参数,返回在current->files->fd[fd]中的地址,即对应文件对象的地址,如果没有任何文件与fd对应,则返回NULL。在第一种情况下,fget( )使文件对象引用计数器f_count的值增1。

当内核完成对文件对象的使用时,调用内核提供的fput() 函数。该函数将文件对象的地址作为参数,并递减文件对象引用计数器f_count的值,另外,如果这个域变为NULL,该函数就调用文件操作的“释放”方法(如果已定义),释放相应的目录项对象,并递减对应索引节点对象的i_writeaccess域的值(如果该文件是写打开),最后,将该文件对象从“正在使用”链表移到“未使用”链表。

3.关于文件系统信息的fs_struct结构

第三个结构是fs_struct,在2.4以前的版本中在include/linux/sched.h中定义为:

struct fs_struct {

atomic_tcount;

intumask;

struct dentry * root, * pwd;

};

在2.4中,单独定义在include/linux/fs_struct.h中:

struct fs_struct {

atomic_tcount;

rwlock_tlock;

intumask;

struct dentry * root, * pwd, * altroot;

struct vfsmount * rootmnt, * pwdmnt, *altrootmnt;

};

count域表示共享同一fs_struct 表的进程数目。umask域由umask( )系统调用使用,用于为新创建的文件设置初始文件许可权。

fs_struct中的dentry结构是对一个目录项的描述,root、pwd及 altroot三个指针都指向这个结构。其中,root所指向的dentry结构代表着本进程所在的根目录,也就是在用户登录进入系统时所看到的根目录;pwd指向进程当前所在的目录;而altroot则是为用户设置的替换根目录。实际运行时,这三个目录不一定都在同一个文件系统中。例如,进程的根目录通常是安装于“/”节点上的Ext2文件系统,而当前工作目录可能是安装于/msdos的一个DOS文件系统。因此,fs_struct结构中的rootmnt、 pwdmnt及 altrootmnt就是对那三个目录的安装点的描述,安装点的数据结构为vfsmount。

 

 

3、验证调用多个atexit函数时的输出顺序

  源码:

#include<stdio.h>

#include<stdlib.h>

 

void fun1()

{

       printf("thefun1\n");

}

void fun2()

{

       printf("thefun2\n");

}

void fun3()

{

       printf("thefun3\n");

}

 

 

int main()

{

       atexit(fun1);

       atexit(fun2);

       atexit(fun3);

 

       printf("the  main\n");

       return0;

}

结果:


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/459446.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QQuickRenderControl

2019独角兽企业重金招聘Python工程师标准>>> http://doc.qt.io/qt-5/qquickrendercontrol.html http://translate.google.com.hk/translate?hlzh-CN&slauto&tlen&uhttp%3A%2F%2Fhabrahabr.ru%2Fpost%2F247477%2F http://www.kdab.com/overview-qt3d-2-…

线程的控制(创建、等待、终止)、分离线程

一、线程控制 1、线程&#xff1a;线程是资源调度的基本单位&#xff0c;线程是进程内部的一个执行流&#xff0c;在进程的地址空间内运行。在Linux 下没有真正意义上的线程&#xff0c;线程是用进程模拟的&#xff0c;又被称为轻量级进程。 2、由于同⼀一进程的多个线程共享同…

从netty-example分析Netty组件

分析netty从源码开始 准备工作&#xff1a; 1.下载源代码&#xff1a;https://github.com/netty/netty.git 我下载的版本为4.1 2. eclipse导入maven工程。 netty提供了一个netty-example工程&#xff0c; 分类如下&#xff1a; Fundamental Echo ‐ the very basic client and …

cep

cep posted on 2015-12-16 17:03 秦瑞It行程实录 阅读(...) 评论(...) 编辑 收藏 转载于:https://www.cnblogs.com/ruiy/p/5051673.html

RHCS集群原理概述

一、 什么是RHCSRHCS是Red Hat Cluster Suite的缩写&#xff0c;也就是红帽集群套件&#xff0c;RHCS是一个能够提供高可用性、高可靠性、负载均衡、存储共享且经济廉价的集群工具集合&#xff0c;它将集群系统中三大集群架构融合一体&#xff0c;可以给web应用、数据库应用等提…

Linux学习笔记11——文件I/O之二

一、文件共享 内核使用三种数据结构表示打开的文件&#xff0c;它们之间的关系决定了在文件共享方面一个进程对另一个进程可能产生的影响。 1、每个进程在进程表中都有一个记录项&#xff0c;记录项中包含有一张打开文件描述表  2、内核为所有打开文件维持一张文件表  3、每…

Git Proxy开关

2019独角兽企业重金招聘Python工程师标准>>> 这个是配合ShadowSocks使用的&#xff0c;在~/.bash_aliases或者~/.bash_profile中设置以下代码&#xff1a; #git proxy enable alias gitpe"git config --global http.proxy socks5://127.0.0.1:1080;git config …

平衡二叉查找树插入节点操作( AVLTree ):旋转、调整平衡

AVL树的插入 在向一棵本来高度平衡的AVL树中插入一个新节点时&#xff0c;如果树中某个结点的平衡因子的绝对值 > 1&#xff0c;则出现了不平衡。设新插入结点为P&#xff0c;从结点P到根节点的路径上&#xff0c;每个结点为根的子树的高度都可能增加1&#xff0c;因此在每…

Fork/Join框架介绍

转http://www.infoq.com/cn/articles/fork-join-introduction/ 1. 什么是Fork/Join框架 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架&#xff0c; 是一个把大任务分割成若干个小任务&#xff0c;最终汇总每个小任务结果后得到大任务结果的框架。 我们再通过Fork和…

为什么析构函数可以能声明为虚函数,构造函数不可以

转自&#xff1a;http://blog.csdn.NET/chen825919148/article/details/8020550 构造函数不能声明为虚函数&#xff0c;析构函数可以声明为虚函数&#xff0c;而且有时是必须声明为虚函数。 不建议在构造函数和析构函数里面调用虚函数。 构造函数不能声明为虚函数的原因是: 1 …

信号集操作函数,信号未决、阻塞、递达

转载&#xff1a;信号集操作函数&#xff0c;信号阻塞与未决 一&#xff0c;信号集及相关操作函数 信号集被定义为一种数据类型&#xff1a; typedef struct { unsigned long sig[_NSIG_WORDS]&#xff1b; } sigset_t 信号集用来描述信号的集合&#xff0c;每个信号占用一位&a…

线程安全和可重入函数的联系与区别

1、 线程安全&#xff1a; 线程安全是多线程访问时&#xff0c;采用了加锁机制&#xff0c;当一个线程访问该类的某个数据时&#xff0c;进行保护&#xff0c;其他线程不能进行访问直到该线程访问完&#xff0c;其他线程才可以使用。不会出现数据不一致或数据污染。 线程不…

C++11 多线程 基础

C11开始支持多线程编程&#xff0c;之前多线程编程都需要系统的支持&#xff0c;在不同的系统下创建线程需要不同的API如pthread_create()&#xff0c;Createthread()&#xff0c;beginthread()等&#xff0c;使用起来都比较复杂&#xff0c;C11提供了新头文件<thread>、…

LB负载均衡集群--LVS

LB集群&#xff1a;LB集群是load balance 集群的简写&#xff0c;翻译成中文就是负载均衡集群。常用的负载均衡开源软件有nginx、lvs、keepalived &#xff0c;商业的硬件负载设备F5、Netscale。LB集群架构&#xff1a;当用户的请求过来时&#xff0c;会直接发到分发器&#xf…

2015 UESTC 搜索专题B题 邱老师降临小行星 记忆化搜索

邱老师降临小行星 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/contest/show/61Description 人赢邱老师和任何男生比&#xff0c;都是不虚的。有一天&#xff0c;邱老师带妹子(们)来到了一个N行M列平面的小行星。对于每一个着陆地点&#xf…

优化表的数据类型

我们可以使用PROCEDURE ANALYSE()对当前已有应用的表类型的判断&#xff0c;该函数可以对数据表中的列的数据类型提出优化建议&#xff0c;可以根据应用的实际情况酌情考虑是否实施优化。语法&#xff1a; SELECT * FROM tbl_name PROCEDURE ANALYSE(); SELECT * FROM tb…

Linux 信号之mysleep

一、 用alarm和pause实现sleep(3)函数,称为mysleep。 1. main函数调用mysleep函数,后者调用sigaction注册了SIGALRM信号的处理函数sig_alrm。 2. 调用alarm(seconds)设定闹钟。 3. 调用pause等待,内核切换到别的进程运行。 4. seconds秒之后,闹钟超时,内核发SIGALRM给这个…

JAVA 操作系统已经来到第五个版本了 现陆续放出三个版本 这是第二个版本

1 package System2;2 3 import javax.swing.*;4 5 import java.awt.*;6 import java.awt.event.ActionEvent;7 import java.awt.event.ActionListener;8 import java.awt.event.KeyListener;9 import java.util.*;10 /**11 * 作者:范铭祥12 * 内容及功能&#xff1a; 显示框…

标准Web系统的架构分层

1、架构体系分层图 在上图中我们描述了Web系统架构中的组成部分。并且给出了每一层常用的技术组件/服务实现。需要注意以下几点&#xff1a; 系统架构是灵活的&#xff0c;根据需求的不同&#xff0c;不一定每一层的技术都需要使用。例如&#xff1a;一些简单的CRM系统可能在产…

数据链路层差错检测:CRC(循环冗余检验)

1、循环冗余检验&#xff08;CRC&#xff09;&#xff1a; 在发送端&#xff0c;先把数据划分为祖&#xff0c;假定每组K个比特。现假定待传送的数据M 101001&#xff08;k6&#xff09;。CRC运算就是在数据M后面添加提供差错检测的n位冗余码&#xff0c;然后构成一个帧发送出…