??xml version="1.0" encoding="utf-8" standalone="yes"?>
1 tcpmux TCP 端口服务多\复用
5 rje q程作业入口
7 echo Echo 服务
9 discard 用于q接试的空服务
11 systat 用于列Dq接了的端口的系l状?
13 daytime l请求主机发送日期和旉
阅读全文
]]>
]]>
]]>
]]>
1、列文g或目录的信息工具 ls或dir;
ls 命o可以用于昄目录的内容,也可以显C文件的属性,比如节点、文件种cR权限、拥有者、大、创建时间等Q在目前最新版本的Linux中dir和ls命o的用法是一L(fng)Q有兴趣的不仿尝试一下;
1.1 ls 的基语法和参敎ͼ
语法格式Q?/strong>
#ls Qd数] [目录或文件名]
参数Q?/strong>
-a 昄所有文Ӟ包含隐藏文gQ包?#8220;.“?#8220;..“
-A 昄所有文Ӟ包含隐藏文gQ不包括“.“?#8220;..“目录Q?br />
-B 不列出文件名以~l尾的文Ӟ
-C 按列列出文gQ?br />
-d 仅可以查看目录的属性参数及信息Q?br />
-F q个参数加上后,能给目录d?Q给可执行文件加?Q给W号链接加上@ {等Q来标记文g名,目的是让用户方便查看Q?
-l 长格式输?br />
-h 习惯Z可阅ȝ方式来显C文件或目录的大,比如K、M或G{;
-p 在目录的后面附加/标记Q?br />
-r 逆序列出文gQ?br />
-t 按文件最后访问(或修改)的时间排序,最新的排在最前面Q?br />
-U 按原始排序,
-L 递归昄Q也是_当我们列某个目录的下的所有文件和目录Ӟ能把它的下目录的内Ҏ(gu)C出来?br />
--help 获得帮助Q?/code>
在这里,位于[]之内的都是可选的。如果?zhn)只输入ls Q就会列出用h处当前目录的所有文Ӟ用短格式输出Q但不会列出隐藏文g?/p>
判断用户所处目录的命o是pwdQ也是
[root@localhost ~]# pwd
/root
1.2 ls 的参数示例应用;
1.21 列出目录下所有文Ӟ包含或不包含隐藏文gQ?a 参数?l参数的运用;
#ls -la Qȝ录名]
如果不接目录名,表示输出当前用户所处目录内的所有文Ӟ包括隐藏文gQ?/p>
[root@localhost ~]# pwd
/root
[root@localhost ~]# ls -la
列出某一目录下的的文件或目录Q但不包括隐藏文Ӟ我们只用-l参数
#ls -l 目录
比如Q?br />
[root@localhost ~]# ls -l /root/
总计 13968
-rw-r--r-- 1 root root 0 04-19 14:09 123.txt
-rw------- 1 root root 1375 03-16 08:55 anaconda-ks.cfg
-rw-r--r-- 1 root root 2 03-27 02:00 fonts.scale
-rw-r--r-- 1 root root 5423 03-16 08:52 install.log.syslog
-rw-r--r-- 1 root root 14087155 03-16 07:53 kernel-2.6.15-1.2025_FC5.i686.rpm
lrwxrwxrwx 1 root root 33 04-19 11:27 kernel.rpm -> kernel-2.6.15-1.2025_FC5.i686.rpm
drwxr-xr-x 2 1000 users 4096 04-04 23:30 mkuml-2004.07.17
-rw-r--r-- 1 root root 68012 04-04 20:28 mkuml-2004.07.17-ananas.tar.bz2
drwxr-xr-x 2 root root 4096 04-19 10:53 mydir
-rw-r--r-- 1 root root 53992 03-16 08:54 myinstall.log
-rw-r--r-- 1 root root 0 04-19 14:10 plinux.txt
drwxr-xr-x 2 root root 4096 03-17 04:25 Public
-rw-r--r-- 1 root root 613 03-26 18:41 upgrade.log
-rw-r--r-- 1 root root 0 03-26 18:39 upgrade.log.syslog
lrwxrwxrwx 1 root root 6 04-19 11:17 yourdir -> mydir/
说明Q如果以长格式输入,d昄出八D内容:
W一D?/strong>文gU类及权限,也就是类DL(fng)-rw-r--r-- Q我们在前面讲到Q如果在q段中,W一字符表示文g的类型,如果出现-Q表C普通文件。如果是d开头的是目录。在q个例子中,123.txt是普通文Ӟ而mkuml-2004.07.17是一个目录。关于文件的U类Q请参?Q?br />
rw-r--r--是权限位Q我们在以后的教E中会讲到?br />
W二D?/strong> 链接个敎ͼ文gpd加一个硬链接Q数字会增加1Q默认从1开始,1表示无硬链接文gQ如果是一个目录,它的默认值应该是2。目录是不能做硬链接的)
查看文g或目录的节点Q我们要用到i参数。如果节点相同,能确认他们是相同的文Ӟ是通过通过ln 创徏的硬链接文gQ链接接有何用?如果(zhn)想把一个文件复制时保持原文件或目录的节炏V大、权限以及访问(或修改)旉都和原文件一致的文g。必通过链接来实现Q用cp命o是不可能实现的?/p>
比如Q?/strong>
我们看一下kernel00.rpm 、kernel.rpm ?kernel-2.6.15-1.2025_FC5.i686.rpm 是不是节点相同?Q他们的大小是不是一P他们的访问日期是不是一P只是他们的文件名不一栗文件名不一h有关p,q能证明其中两个文g是由另一个文仉过ln 创徏而成?/p>
(zhn)可以尝试着用cp ?kernel-2.6.15-1.2025_FC5.i686.rpm 复制为kernel002.rpm Q看看能不能保持节点相同Q?/p>
不是是kernel002.rpm 的节点和 kernel-2.6.15-1.2025_FC5.i686.rpm 不一样了Q?/p>
ls 昄目录的内Ҏ(gu)Q会文件按a到z的字母顺序显C,优先U如下;
也就是说如果不加M排序的参敎ͼ文g名第一个字母是数字的,优先显C;其次才是AQZQ然后才是a-zQ下面是几个排序的参敎ͼ大家l习一下就知道了;
举例
举例Q?/p>
递归昄目录下的所有文Ӟ如果该目录下有子目录Q也会把子目录的文g一q显C出来?/p>
比如
注:也就是把Linux?根目录下的所有文件显C出来,但不会显C隐藏文件。自p着输入上面的命令就知道怎么回事了?/p>
在一般的情况下,ls输出内容是有颜色的,比如目录是蓝Ԍ压羃文g是红字的昄。如果没有颜Ԍ可以加上参数。当然也可以L颜色?/p>
举例Q?/strong>
如果(zhn)的l端或控制台输出的内Ҏ(gu)有颜Ԍ可以自己来定义。在当前用户的家目录下的.bashrc 中加入下面的一行;
举例Q?/strong> 比如我们昄以k开头的所有文Ӟ?root目录中的Q?/p>
我们昄以数字开头的所有文Ӟ
下面是一?通配W的CZQ?/p>
ls 的用法比较简单,至于更详l的参考,q是查man和help。遇C会的Q就查手册,我也是这么做的?/p>
mv 命o是用来移动文件或目录的;有以下几U格式;
参数-i Q表CZhZ互模式;提示警告信息Q?/strong> 举例Q?/strong>
mv 也能和通配W结合一起用,q样能把怼特征的文件移动到某处Q?/strong>
注:参数是可选的Q常用参数比?-r,-R,-p,-i Q?/p>
参数说明Q部份) -a {同?dpR参数一起用;在复制过E中可能保留源文g或目录的属性;
注:人机交互在数-i的运用;如果源文件复制到目标文gQ如果目标文件存在,则提C告; 把源目录复制到另外的一个目标,相当于克隆了一个目录,源目录和目标目录在用L(fng)、权限及修改或访问时间保持一_
注:复制目录mydir 到youdir Q如果yourdir目录不存在,则创建。ƈ且把mydir中所有的文g下子目录都复制?yourdir目录中。也是说mydir目录的文件和youdir是一L(fng)?a 参数{同?dpRQƈ且源目录和目标目录的属性(用户l、权限、最后访问及修改旉Q都一_ 把源文g复制为目标文Ӟq且试-b参数的运用;
比如我们把位于用户当前目录下的fonts.dir、Kernel.rpm和Plist文gQ复制到当前用户所处的目录下的sun目录中;
注:如果(zhn)想把多个目录或文g复制到目标目录时Q?zhn)得加参?-R 复制一个目录到另一个目录时Q我们要用到 -r?R ?a Q?如果目标目录不存在,则创建它Q如果目标目录存在,则复制源目录到目标目录之下;看看-a?R?r有什么不同?试看看Q?/p>
比如我们在用户当前操作的目录中,有mydir目录Q我们想把mydir复制为medirQ在复制之前medir是不存在的)?/p>
如果(zhn)把-R参数换成-a参数Q会有什么不同?看看前面的例子所说的Q?/p>
语法格式
参数常用的如下: -m 在创建目录时要授其权限,要和chmod的授权格式; 我们要创Z个目录linuxsirQƈ且linuxsir目录下包含子目录sirdocQsirdoc目录下还?redhat目录Q?/p>
举例Q?/strong> -m 参数的应用示例; 我们以不同的权限来创建目录,然后查看我们所创徏目录的属性;q要涉及到chown 来改变目录的权限的格式。我们会在以后讲到chown改变目录或文件的权限。在q里不同的是Q在目录创徏之时q其授权了Q?/p>
rmdir 是用来删除空目录用的Q如果目录中有文件或子目录,必须先删除文件或子目录,其语法格式如下:
-p 删除目录时是一U一U的时行的,值得注意的是Q首先从最里面的目录开始。下面是一个例子;
rmdir 所删除的目录,每目录中都是空的,没有其它的文件。如果Q何一U的目录有文Ӟ也不能删除。这时?zhn)要用到rm -rf 命o强制删除。不q用rm -rf 删除时有点不安全Q还是用rf -ri 比较好一点,因ؓ在删除的时候,会有警告提示。这对于安全操作来说是很重要的;
有时我们Z方便Q可能在控制台或l端下创Z个不存在的空文gQ然后我们再用编辑器来编辑它Q创建空文g有时q有点用。说说也无妨。我们在q里用touch、ech0及cat 工具。其实这些工P创徏文g只是他们的一个小的功能Q我们以后再介绍q些工具Q先说他们创建文件的功能?/p>
注意Q创些文Ӟ在我们操作创建文件之前,q些文g在用户当前操作目录下是不存在的,我们在这里只是创Z个新的文件名Qƈ且它里面没有MI容的;
rm 是用来删除一个或多个文g的工Pq且能用于删除非I目录。我们前面提C可以加参?rf 可以强制删除一个非I目录?/p>
rm的语法格式;
rm 常用参数Q?/strong>
比如我们惛_除mydir目录及所有下U目录和文gQ要有提C的警告信息Q可以用-r参数?i参数的组合;如果(zhn)想l止rm命oQ请按ctrl+cl合健退出rmQ?/p>
如果(zhn)想没有M警告信息的删除mydir目录下的所有文件及子目录,可以?r?f参数的组合;
mv 可以Ud一个文Ӟ或目录)到另一个文Ӟ或目录)Q如果文Ӟ或目录)不存在,则创建它。其实mv q个q程也可以理解ؓ改名q程Q所以说mv工具能修Ҏ(gu)件名和目录名?/p>
注意Q?/strong>新文件名或目录名应该不能与现有文件名Q或目录名)同名?/p>
举例Q?/strong>
再看一例mv 修改目录的。当然mv是把文gQ或目录Q从一个地方移到另一个地斏V如果另一地方没有和源文gQ或目录Q同名的Q就创徏。这也相当于改名Q?/p>
如果我们不以长格式输出的话,可以把参数省略;
W三D?/strong> 文g或目录所占用的字节数Q如果?zhn)想用K来表C,L(fng)ls -lh /root
W四D?最后访问日?br />
W五D?/strong> 最后访问时?br />
W六D?/strong> 文g?/p>
[root@localhost ~]# ls /root
1.22 仅查看目录的属性的-d参数的运用示例;
[root@localhost ~]# ls -ld /etc /boot 注:查看/etc?boot目录的信息;
drwxr-xr-x 4 root root 4096 04-11 16:22 /boot
drwxr-xr-x 108 root root 12288 04-20 12:36 /etc
1.23 查看文g或目录的inode节点Q?i参数的运用;
[root@localhost ~]# ls -li /root
[root@localhost ~]# ls -li kernel*
2408323 -rw-r--r-- 3 root root 14087155 03-16 07:53 kernel00.rpm
2408270 lrwxrwxrwx 1 root root 33 04-19 14:56 kernel1.rpm -> kernel-2.6.15-1.2025_FC5.i686.rpm
2408323 -rw-r--r-- 3 root root 14087155 03-16 07:53 kernel-2.6.15-1.2025_FC5.i686.rpm
2408323 -rw-r--r-- 3 root root 14087155 03-16 07:53 kernel.rpm[root@localhost ~]# ls -li kernel*
2408272 -rw-r--r-- 1 root root 14087155 04-19 16:05 kernel002.rpm
2408323 -rw-r--r-- 3 root root 14087155 03-16 07:53 kernel00.rpm
2408270 lrwxrwxrwx 1 root root 33 04-19 14:56 kernel1.rpm -> kernel-2.6.15-1.2025_FC5.i686.rpm
2408323 -rw-r--r-- 3 root root 14087155 03-16 07:53 kernel-2.6.15-1.2025_FC5.i686.rpm
2408323 -rw-r--r-- 3 root root 14087155 03-16 07:53 kernel.rpm
1.24 关于排序的参数的应用Q?br />
数字
a-z
A-Z在文件的大小排序上,我们要用?S参数Q?
如果是逆序排序Ӟ我们要用?r参数Q?br />
按最后访问的时候排序,要用?t参数Q?br />
Ҏ(gu)扩展名进行排序,要用到参?-X Q?[root@localhost ~]# ls
123.txt fonts.scale kernel myinstall.log upgrade.log
anaconda-ks.cfg install.log.syslog mkuml-2004.07.17-ananas.tar.bz2 plinux.txt upgrade.log.syslog[root@localhost ~]# ls -lS /root
[root@localhost ~]# ls -lS
总计 180
-rw-r--r-- 1 root root 68012 04-04 20:28 mkuml-2004.07.17-ananas.tar.bz2
-rw-r--r-- 1 root root 53992 03-16 08:54 myinstall.log
-rw-r--r-- 1 root root 5423 03-16 08:52 install.log.syslog
drwxr-xr-x 2 root root 4096 04-19 20:04 kernel
-rw------- 1 root root 1375 04-19 15:04 anaconda-ks.cfg
-rw-r--r-- 1 root root 613 03-26 18:41 upgrade.log
-rw-r--r-- 1 root root 21 04-19 15:06 123.txt
-rw-r--r-- 1 root root 2 03-27 02:00 fonts.scale
-rw-r--r-- 1 root root 0 04-19 14:10 plinux.txt
-rw-r--r-- 1 root root 0 03-26 18:39 upgrade.log.syslog[root@localhost ~]# ls -lr
总计 180
-rw-r--r-- 1 root root 0 03-26 18:39 upgrade.log.syslog
-rw-r--r-- 1 root root 613 03-26 18:41 upgrade.log
-rw-r--r-- 1 root root 0 04-19 14:10 plinux.txt
-rw-r--r-- 1 root root 53992 03-16 08:54 myinstall.log
-rw-r--r-- 1 root root 68012 04-04 20:28 mkuml-2004.07.17-ananas.tar.bz2
drwxr-xr-x 2 root root 4096 04-19 20:04 kernel
-rw-r--r-- 1 root root 5423 03-16 08:52 install.log.syslog
-rw-r--r-- 1 root root 2 03-27 02:00 fonts.scale
-rw------- 1 root root 1375 04-19 15:04 anaconda-ks.cfg
-rw-r--r-- 1 root root 21 04-19 15:06 123.txt[root@localhost ~]# ls -lt
总计 180
drwxr-xr-x 2 root root 4096 04-19 20:04 kernel
-rw-r--r-- 1 root root 21 04-19 15:06 123.txt
-rw------- 1 root root 1375 04-19 15:04 anaconda-ks.cfg
-rw-r--r-- 1 root root 0 04-19 14:10 plinux.txt
-rw-r--r-- 1 root root 68012 04-04 20:28 mkuml-2004.07.17-ananas.tar.bz2
-rw-r--r-- 1 root root 2 03-27 02:00 fonts.scale
-rw-r--r-- 1 root root 613 03-26 18:41 upgrade.log
-rw-r--r-- 1 root root 0 03-26 18:39 upgrade.log.syslog
-rw-r--r-- 1 root root 53992 03-16 08:54 myinstall.log
-rw-r--r-- 1 root root 5423 03-16 08:52 install.log.syslog
1.25 递归昄目录的文Ӟ-R参数的应用;
[root@localhost ~]# ls -lR /
1.26 关于ls 输出内容在终端显C颜色的参数 --colorQ?br />
--color=never 表示输出输出没有彩色
--color=auto 表示自动
--color=always 表示输出内容有彩?[root@localhost ~]# ls -la --color=never
[root@localhost ~]# ls -la --color=any
[root@localhost ~]# ls -la --color=alwaysalias ls="ls --color=always"
1.27 ls?F参数的示例;
[root@localhost ~]# ls -F
crondw.sh* kernel/ mkuml-2004.07.17-ananas.tar.bz2 openQreadme.txt@ sun.txt upgrade.log youdir/
[root@localhost ~]# ls -lF
总计 92
-rwxr-xr-x 1 root root 0 04-20 14:18 crondw.sh*
drwxr-xr-x 3 root root 4096 04-20 14:17 kernel/
-rw-r--r-- 1 root root 68012 04-04 20:28 mkuml-2004.07.17-ananas.tar.bz2
lrwxrwxrwx 1 root root 7 04-20 14:18 openQreadme.txt -> sun.txt
-rw-r--r-- 1 root root 11 04-20 14:17 sun.txt
-rw-r--r-- 1 root root 613 03-26 18:41 upgrade.log
drwxr-xr-x 6 root root 4096 04-20 14:17 youdir/
1.3 通配W在ls命o中的应用Q?br />
* 代表0个或多个字符
[]内部包括M字符
? M单个字符[root@localhost ~]# ls /root/k*
kernel002.rpm kernel00.rpm kernel1.rpm kernel-2.6.15-1.2025_FC5.i686.rpm kernel.rpm[root@localhost ~]# ls [0-9]*
123.txt 234.txt 2kexe.txt 6mns.doc[root@localhost ~]# ls *.t?t
123.txt 234.txt 2kexe.txt 333.tot plinux.txt
1.4 获得ls 的帮助;
[root@localhost ~]# ls --help
[root@localhost ~]# man ls
[root@localhost ~]# info ls
2、移动文件或目录的命?mv Q?br />
#mv file1 file2 注:把file1Ud到file2Q如果file2不存在,则创建file2文g名;
#mv file1 dir 注:把一个文件移动到一个事实存在的目录Q?br />
#mv dir1 dir2 Ud目录dir1 ?dir2 Q如果dir2不存在,则创建它Q?br />
#mv file1 file2 file3 ... ... dir Udfile1、file2、file3{多个文件到dir目录中;
#mv dir1 dir2 ... ... dirn 注:Ud目录dir1和dir2{多个目录到dirn目录?/code>[root@localhost ~]# mv -i 123.txt 234.txt
mvQ是否覆?#8220;234.txt”? y 注:要在q里输入yQ表C允许覆?34.txt文gQ如果是nQ请CZ允许Q?/code>* 代表0个或多个字符
[]内部包括M字符
? M单个字符
举例Q比如移动以数字开头的文g或目录到 root目录下的tmp目录中;
[root@localhost ~]# pwd
/root
[root@localhost ~]# mv [0-9]* tmp/
[root@localhost ~]# ls -lh tmp/
总计 4.0K
-rw-r--r-- 1 root root 21 04-19 15:06 234.txt
-rw-r--r-- 1 root root 0 04-19 22:23 2kexe.txt
-rw-r--r-- 1 root root 0 04-19 22:25 333.tot
-rw-r--r-- 1 root root 0 04-19 22:23 6mns.doc
3、文件或目录的复制工具cp Q?br />
3.1 cp 的语法和参数
#cp Qd数选项] 源文件或目录 目标文g或目?/code>
-b l被覆盖的文件做备䆾。比如我们把file1 复制到file2Ӟ如果file2存在Q我们把file2覆盖掉,用这个参数就能同时生成一个file2~的文Ӟ注意文g名后有~l尾
-d 不间接引用符号链接,保持源文件和目标文g之间的硬链接关系Q?br />
-f 删除已存在的目标文gQ?br />
-i 覆盖已存在的目标文g之前l出警告提示Q这是hZ互的选项Q?br />
-l 建立文g链接,而不是复Ӟ
-p 保存源文件或目录的最后修Ҏ(gu)间和模式Q比如要保持目标目录或文件的属主、组、权限和最后访问(或修改)旉Q?br />
-R 复制目录Ӟ包括淅目录下所有的子目录和文gQ?br />
-s 建立源文件的W号链接Q而不是复制源文g。源文g名必ȝl对路径Q?br />
-r 复制目录Ӟ包括淅目录下所有的子目录和文gQ?r选项不同?R之处在于 试打开目的地文件前先删除已存在的目的地文g
-i 人机交互模式Q显法覆盖已存在的文件或目录的警告信息;
-v 在复制之前,输出每个文g的名字;
--help 查看帮助 Q?/p>
3.2 CZ说明cp应用Q?br />
3.21 参数-i的示例;
[root@localhost ~]# ls
anaconda-ks.cfg install.log.syslog Kernel.rpm mydir Plist upgrade.log youdir
fonts.scale kernel mkuml-2004.07.17-ananas.tar.bz2 plinux.txt sun upgrade.log.syslog
[root@localhost ~]# pwd
/root
[root@localhost ~]# cp -i Kernel.rpm Plist
cpQ是否覆?#8220;Plist”? y
3.22 参数-a的示例及说明Q?br />
[root@localhost ~]# cp -a mydir youdir
3.23 参数-b的示例应用;
[root@localhost ~]# cp fonts.scale fonts.dir 把一个文件复制ؓ另一个文Ӟ
[root@localhost ~]# cp -bi fonts.scale fonts.dir
cpQ是否覆?#8220;fonts.dir”? y 注:因ؓ用了-i 参数Q如果目标文件存在,则报警提C;
[root@localhost ~]# ls -lh fonts.*
-rw-r--r-- 1 root root 2 04-20 10:24 fonts.dir
-rw-r--r-- 1 root root 2 04-20 10:24 fonts.dir~ 注:-b参数q用的效果就是生成已存在目标文g的覆盖之前备份?br />
-rw-r--r-- 1 root root 2 03-27 02:00 fonts.scale
3.24 把多个文件复制到目录目录中示例;
[root@localhost ~]# pwd 注:判断用户所处的位置Q也是所处的目录Q?br />
/root
[root@localhost ~]# mv fonts.dir Kernel.rpm Plist sun/
[root@localhost ~]# ls sun/
fonts.dir Kernel.rpm Plist
3.25 复制目录?R参数的应用;
[root@localhost ~]# cp -R mydir medir 注:如果medir目录不存在,则创建medir目录Qƈ且medir目录中的内容和mydir中的一P
4?目录创徏工具mkdir和删除空目录工具rmdirQ?br />
4.1 mkdir 是目录创建工P
4.11 mkdir语法格式及参敎ͼ
#mkdir [参数选项] 目录
-p 如果中间目录不存在,则创建它
4.12 参数 -p 的应用示?br />
[root@localhost ~]# mkdir -p linuxsir/sirdoc/redhat
[root@localhost ~]# mkdir -m 644 sundir
[root@localhost ~]# mkdir -m 755 moondir
[root@localhost ~]# mkdir -m 000 beinandir
[root@localhost ~]# ls -ld sundir moondir beinandir
d--------- 2 root root 4096 04-20 11:01 beinandir
drwxr-xr-x 2 root root 4096 04-20 11:01 moondir
drw-r--r-- 2 root root 4096 04-20 11:00 sundir
4.2 删除I目录工?rmdir 和rm Q?br />
#rmdir Qd数] 目录
rmdir 参数常用的有Q?br />
[root@localhost ~]# mkdir -p linuxsir/sirdoc/redhat/
注:首先在当前目录下创徏linuxsir目录Q他的子目录是sirdocQsirdoc内又有一个子目录redhat
[root@localhost ~]# rmdir -p linuxsir/sirdoc/redhat/ 注:删除linuxsir目录Q要用到参数-p
[root@localhost ~]# ls linuxsir 注:查一下是不是q有q个目录Q?
ls: linuxsir: 没有那个文g或目?/code>[root@localhost ~]# ls -lh sun/ 注:q是sun目录Q里面有内容Q?br />
总计 28K
-rw------- 1 root root 1.4K 04-19 15:04 anaconda-ks.cfg
-rw-r--r-- 1 root root 2 04-20 10:24 fonts.dir
-rw-r--r-- 1 root root 2 03-27 02:00 fonts.scale
-rw-r--r-- 1 root root 5.3K 03-16 08:52 install.log.syslog
-rw-r--r-- 1 root root 0 04-19 20:44 Kernel.rpm
-rw-r--r-- 1 root root 0 04-20 10:20 Plist
[root@localhost ~]# rmdir sun/ 注:我们试用rmdir来删除,
rmdir: sun/: 目录非空
[root@localhost ~]# rm -rf sun/ 注:强制用rm -rf 来删除;
[root@localhost ~]# ls sun 注:查是否删除,删除成功Q?br />
ls: sun: 没有那个文g或目?/code>
5、创Z个空文g的工P?touch、echo、cat{工P
[root@localhost ~]# ls 123456.txt 654321.txt 98765.txt
ls: 123456.txt: 没有那个文g或目?br />
ls: 654321.txt: 没有那个文g或目?br />
ls: 98765.txt: 没有那个文g或目?/code>[root@localhost ~]# echo > 123456.txt 注:用ech0 来创建,在创Z前在此操作目录下不存?23456.txt文gQ?br />
[root@localhost ~]# ls 123456.txt 注:查看一下看有没有生成?
123456.txt [root@localhost ~]# touch 654321.txt 注:?touch 来创建,在创Z前在此操作目录下不存?54321.txt文gQ?br />
[root@localhost ~]# ls 654321.txt 注:查看一下看有没有生成?
654321.txt[root@localhost ~]# cat > 98765.txt 注:用ech0 来创建,在创Z前在此操作目录下不存?8765.txt 文gQ然后按ctrl+cl合键退出;
[root@localhost ~]# ls 98765.txt 注:查看一下看有没有生成?
98765.txt
6、删除文件工具rmQ?br />
#rm Qd数选项Q?file1 file2 ... ...
#rm Qd数选项] dir1 dir2 dir3 ... ...-f 不显C告或提示信息删除,用的时候需要小心;
-i 删除文gӞ昄警告信息Q要多用Q这h较安全;Ҏ(gu)提示Q输入ypC删除,输入nQ请CZ删除Q?br />
-r?R 表示可以删除整个目录Q包括子目录及所有文ӞQ要心用;[root@localhost ~]# rm -i 123.sh 注:q是删除一个文Ӟ?i参数的示例,有警告提C;
rmQ是否删除一般空文g“123.sh”? y[root@localhost ~]# rm -ri mydir/
rmQ是否进入目?#8220;mydir/”? y
rmQ是否进入目?#8220;mydir//youdir”? y
rmQ是否删除一般文?#8220;mydir//youdir/enteruml.sh”?[root@localhost ~]# rm -rf mydir
7、修Ҏ(gu)件名工具 mv
#mv 原文件名或目录名 新文件或目录?
[root@localhost ~]# ls
crondw.sh kernel mkuml-2004.07.17-ananas.tar.bz2 mydir openQreadme.txt sun.txt upgrade.log youdir
[root@localhost ~]# mv crondw.sh 123.sh 注:Udcrondw.sh ?23.sh Q其实就是把文g名改Z123.sh
[root@localhost ~]# ls
123.sh kernel mkuml-2004.07.17-ananas.tar.bz2 mydir openQreadme.txt sun.txt upgrade.log youdir
[root@localhost ~]# ls
123.sh kernel mkuml-2004.07.17-ananas.tar.bz2 mydir openQreadme.txt sun.txt upgrade.log youdir
[root@localhost ~]# mv kernel/ kernelBak
[root@localhost ~]# ls
123.sh kernelBak mkuml-2004.07.17-ananas.tar.bz2 mydir openQreadme.txt sun.txt upgrade.log youdir
]]>
# locale
LANG=en_US.UTF-8
LC_CTYPE=zh_CN.UTF-8
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
# vim
查看默认的字W编?br />
:set fileencodings
fileencodings=utf-8,latin1
2>实现
知道了上面这些,当我们在打开一个其它编码的文gӞ只要先设|一下vi/vim的fileencodings值就可以了?br />
(1)动态设|实?br />
# vim
:set fileencodings gb2312,utf-8
多个字符~码?#8220;Q?#8221;隔开?br />
(2)配置文g静态设|实?br />
配置一下vi/vim的配|文Ӟ
vi ~/.vimrc
set fileencodings=utf-8,gb2312
]]>
-a 列出目录下的所有文Ӟ包括?. 开头的隐含文g?br />
-b 把文件名中不可输出的字符用反斜杠加字W编?p在C语言里一?的Ş式列出?br />
-c 输出文g?i 节点的修Ҏ(gu)_q以此排序?br />
-d 目录象文g一hC,而不是显C其下的文g?br />
-e 输出旉的全部信息,而不是输出简略信息?br />
-f -U 对输出的文g不排序?br />
-g 无用?br />
-i 输出文g?i 节点的烦引信息?br />
-k ?k 字节的Ş式表C文件的大小?br />
-l 列出文g的详l信息?br />
-m 横向输出文g名,q以“Q?#8221;作分格符?br />
-n 用数字的 UID,GID 代替名称?br />
-o 昄文g的除l信息外的详l信息?br />
-p -F 在每个文件名后附上一个字W以说明该文件的cdQ?#8220;*”表示可执行的普?br />
文gQ?#8220;/”表示目录Q?#8220;@”表示W号链接Q?#8220;|”表示FIFOsQ?#8220;=”表示?br />
接字(sockets)?br />
-q ?代替不可输出的字W?br />
-r 对目录反向排序?br />
-s 在每个文件名后输文g的大?br />
-t 以时间排序?br />
-u 以文件上ơ被讉K的时间排序?br />
-x 按列输出Q横向排序?br />
-A 昄?“.”?#8220;..”外的所有文件?br />
-B 不输Z “~”l尾的备份文件?br />
-C 按列输出Q纵向排序?br />
-G 输出文g的组的信息?br />
-L 列出链接文g名而不是链接到的文件?br />
-N 不限制文仉度?br />
-Q 把输出的文g名用双引hh?br />
-R 列出所有子目录下的文g?br />
-S 以文件大排序?br />
-X 以文件的扩展?最后一?. 后的字符)排序?br />
-1 一行只输出一个文件?br />
--color=no 不显C彩色文件名
--help 在标准输Z昄帮助信息?br />
--version 在标准输Z输出版本信息q出?
]]>
如上所qͼ~ 表示(zhn)的 home 目录。与之类似的写Ş?~username 表示 username ?home 目录。例如,~joe 表示 joe ?home 目录Q所以,要将文g?joe ?doc 目录复制到?zhn)?info 目录Q?zhn)可以输入下面的命令?
代码:
$ cp ~joe/doc/report.txt ~/info
另一个有用的W号?..Q两个点PQ这是当前目录的父目录的写。?.. ?.Q当前工作目录的写符PQ?zhn)可以引用文gpȝ中相对于当前工作目录的文件和目录?br />
例如Q如果?zhn)的当前工作目录?~/jane/projects/lambdaQ那么简?../.. 表示向上两目录的目录,?~/jane。要表示包含 ~/jane 的目录,(zhn)可以?../../../Q?#8220;向上三目录”Q或路径 ~jane/../。后面的q个路径表示?~jane 开始,然后转到上一U目录?br />
要将文g复制到?zhn)的当前目录,不需要指定目标目录,可以直接使用 .Q?#8220;?#8221;Q来表示Q?
$ cp -pr /path/to/lots/of/stuff
用L号快速修改输错的命o
假如打错了一个很长的命oQ需要重新输入是十分沮的事情。例如:
$ find . -naem "*.txt" -print
的例子中Qname 被错误的输成?naem Q我们能够用下面的L符h替换Q?br />
$ ^em^me^
find . -name "*.txt" -print
验?zhn)的工?/strong>
如果(zhn)想要查看命令行W号扩展后的l果Q可以?echo 命oQ?
$ echo ~joe/doc/report.txt ~/info
/guests/joe/doc/report.txt /staff/bobr/info
$ echo $SHELL
/bin/zsh
$ ls
architecture.txt Services.pdf
services.txt Schema.pdf
$ echo *.txt
architecture.txt services.txt
]]>
在多d操作pȝ环境中,如果一个进E尝试对正在被其他进E读取的文gq行写操作,可能会导致正在进行读操作的进E读取到一些被破坏或者不完整的数据;如果两个q程q发对同一个文件进行写操作Q可能会D该文仉到破坏。因此,Z避免发生q种问题Q必要采用某种机制来解军_个进Eƈ发访问同一个文件时所面(f)的同步问题,由此而生了文g加锁斚w的技术?/p>
早期?UNIX pȝ只支持对整个文gq行加锁Q因此无法运行数据库之类的程序,因ؓ此类E序需要实现记录的加锁。在 System V Release 3 中,通过 fcntl 提供了记录的加锁,此后发展成ؓ POSIX 标准的一部分。本文将Z 2.6.23 版本的内核来探讨 Linux 中文仉的相x术?/p>
Linux 支持的文仉技术主要包括劝告锁Qadvisory lockQ和强制锁(mandatory lockQ这两种。此外,Linux 中还引入了两U强刉的变UŞ式:׃n模式强制锁(share-mode mandatory lockQ和U借锁QleaseQ?/p>
?Linux 中,不论q程是在使用劝告锁还是强刉Q它都可以同时用共享锁和排他锁Q又UCؓ读锁和写锁)。多个共享锁之间不会怺q扰Q多个进E在同一时刻可以对同一个文件加׃n锁。但是,如果一个进E对该文件加了排他锁Q那么其他进E则无权再对该文件加׃n锁或者排他锁Q直到该排他锁被释放。所以,对于同一个文件来_它可以同时拥有很多读者,但是在某一特定时刻Q它只能拥有一个写者,它们之间的兼容关pd?1 所C?/p>
劝告锁是一U协同工作的锁。对于这一U锁来说Q内核只提供加锁以及文件是否已l加锁的手段Q但是内核ƈ不参与锁的控制和协调。也是_如果有进E不遵守“游戏规则”Q不查目标文件是否已l由别的q程加了锁就往其中写入数据Q那么内核是不会加以L的。因此,劝告锁ƈ不能Lq程Ҏ(gu)件的讉KQ而只能依靠各个进E在讉K文g之前查该文g是否已经被其他进E加锁来实现q发控制。进E需要事先对锁的状态做一个约定,q根据锁的当前状态和怺关系来确定其他进E是否能Ҏ(gu)件执行指定的操作。从q点上来_劝告锁的工作方式与用信号量保护临界区的方式非常cM?/p>
劝告锁可以对文g的Q意一个部分进行加锁,也可以对整个文gq行加锁Q甚臛_以对文g来增大的部分也q行加锁。由于进E可以选择Ҏ(gu)件的某个部分q行加锁Q所以一个进E可以获得关于某个文件不同部分的多个锁?/p>
与劝告锁不同Q强刉是一U内核强刉用的文g锁,它是?System V Release 3 开始引入的。每当有pȝ调用 open()、read() 以及write() 发生的时候,内核都要查ƈ保q些pȝ调用不会q反在所讉K文g上加的强刉U束。也是_如果有进E不遵守游戏规则Q硬要往加了锁的文g中写入内容,内核׃加以LQ?/p>
如果一个文件已l被加上了读锁或者共享锁Q那么其他进E再对这个文件进行写操作׃被内栔R止; 如果一个文件已l被加上了写锁或者排他锁Q那么其他进E再对这个文件进行读取或者写操作׃被内栔R止?/p>
如果其他q程试图讉K一个已l加有强刉的文Ӟq程行ؓ取决于所执行的操作模式和文g锁的cdQ归U_?2 所C: 需要注意的是,如果要访问的文g的锁cd与要执行的操作存在冲H,那么采用d?写操作的q程会被dQ而采用非d?写操作的q程则不会阻塞,而是立即q回 EAGAIN?/p>
另外Qunlink() pȝ调用q不会受到强刉的媄响,原因在于一个文件可能存在多个硬链接Q此时删除文件时q不会修Ҏ(gu)件本w的内容Q而是只会改变其父目录?dentry 的内宏V?/p>
然而,在有些应用中q不适合使用强制锁,所以烦引节点结构中?i_flags 字段中定义了一个标志位MS_MANDLOCK用于有选择地允许或者不允许对一个文件用强刉。在 super_block l构中,也可以将 s_flags q个标志|ؓ1或?Q用以表C整个设备上的文件是否允怋用强刉?/p>
要想对一个文仉用强刉Q必L照以下步骤执行: 使用 -o mand 选项来挂载文件系l。这样在执行 mount() pȝ调用Ӟ会传?MS_MANDLOCK 标记Q从而将 super_block l构中的 s_flags 讄?1Q用来表C在q个文gpȝ上可以采用强刉。例如:
是否满h
当前加上的锁
׃n?
排他?
?
?
?
׃n?
?
?
排他?
?
?
当前锁类?
d?
d?
非阻塞读
非阻塞写
读锁
正常d数据
d
正常d数据
EAGAIN
写锁
d
d
EAGAIN
EAGAIN
# mount -o mand /dev/sdb7 /mnt # mount | grep mnt /dev/sdb7 on /mnt type ext3 (rw,mand) |
1.修改要加强制锁的文g的权限:讄 SGID 位,q清除组可执行位。这U组合通常来说是毫无意义的Q系l用来表C文g被加了强刉。例如:
# touch /mnt/testfile # ls -l /mnt/testfile -rw-r--r-- 1 root root 0 Jun 22 14:43 /mnt/testfile # chmod g+s /mnt/testfile # chmod g-x /mnt/testfile # ls -l /mnt/testfile -rw-r-Sr-- 1 root root 0 Jun 22 14:43 /mnt/testfile |
2.使用 fcntl() pȝ调用对该文gq行加锁或解锁操作?/p>
1.3. ׃n模式?/em>
Linux 中还引入了两U特D的文g锁:׃n模式强制锁和U借锁。这两种文g锁可以被看成是强刉的两U变UŞ式。共享模式强刉可以用于某些U有|络文gpȝQ如果某个文件被加上了共享模式强刉Q那么其他进E打开该文件的时候不能与该文件的׃n模式强制锁所讄的访问模式相冲突。但是由于可UL性不好,因此q不使用q种锁?/p>
采用强制锁之后,如果一个进E对某个文g拥有写锁Q只要它不释放这个锁Q就会导致访问该文g的其他进E全部被d或不断失败重试;即该进E只拥有读锁Q也会造成后箋更新该文件的q程的阻塞。ؓ了解册个问题,Linux 中采用了一U新型的U借锁?/p>
当进E尝试打开一个被U借锁保护的文件时Q该q程会被dQ同Ӟ在一定时间内拥有该文件租借锁的进E会收到一个信受收C号之后,拥有该文件租借锁的进E会首先更新文gQ从而保证了文g内容的一致性,接着Q该q程释放q个U借锁。如果拥有租借锁的进E在一定的旉间隔内没有完成工作,内核׃自动删除q个U借锁或者将该锁q行降Q从而允许被d的进El工作?/p>
pȝ默认的这D间隔时间是 45 U钟Q定义如下:
137 int lease_break_time = 45; |
q个参数可以通过修改 /proc/sys/fs/lease-break-time q行调节Q当Ӟ/proc/sys/fs/leases-enable 必须?1 才行Q?/p>
![]() ![]() |
?Linux 内核中,所有类型的文g锁都是由数据l构 file_lock 来描q的Qfile_lock l构是在 文g中定义的Q内容如下所C:
811 struct file_lock { 812 struct file_lock *fl_next; /* singly linked list for this inode */ 813 struct list_head fl_link; /* doubly linked list of all locks */ 814 struct list_head fl_block; /* circular list of blocked processes */ 815 fl_owner_t fl_owner; 816 unsigned int fl_pid; 817 wait_queue_head_t fl_wait; 818 struct file *fl_file; 819 unsigned char fl_flags; 820 unsigned char fl_type; 821 loff_t fl_start; 822 loff_t fl_end; 823 824 struct fasync_struct * fl_fasync; /* for lease break notifications */ 825 unsigned long fl_break_time; /* for nonblocking lease breaks */ 826 827 struct file_lock_operations *fl_ops; /* Callbacks for filesystems */ 828 struct lock_manager_operations *fl_lmops; /* Callbacks for lockmanagers */ 829 union { 830 struct nfs_lock_info nfs_fl; 831 struct nfs4_lock_info nfs4_fl; 832 struct { 833 struct list_head link; /* link in AFS vnode's pending_locks list */ 834 int state; /* state of grant or error if -ve */ 835 } afs; 836 } fl_u; 837 }; |
?3 单描qC file_lock l构中的各个字段所表示的含义?/p>
一?file_lock l构是一?#8220;?#8221;Q结构中?fl_file 指向目标文件的 file l构Q?fl_start ?fl_end 则确定了该文件要加锁的一个区域。当q程发出pȝ调用来请求对某个文g加排他锁Ӟ如果q个文g上已l加上了׃n锁,那么排他锁请求不能被立即满Q这个进E必d要被d。这Pq个q程p放进了等待队列,file_lock l构中的 fl_wait 字段指向这个等待队列。指向磁盘上相同文g的所?file_lock l构会被链接成一个单链表 file_lock_listQ烦引节点结构中?i_flock 字段会指向该单链表结构的首元素,fl_next 用于指向该链表中的下一个元素;当前pȝ中所有被hQ但是未被允许的锁被串成一个链表:blocked_list。fl_link 字段指向q两个列表其中一个。对于被d列表Qblocked_listQ上的每一个锁l构来说Qfl_next 字段指向与该锁生冲H的当前正在使用的锁。所有在{待同一个锁的那些锁会被链接hQ这需要用到字D?fl_blockQ新来的{待者会被加入到{待列表的尾部?此外Qfl_type 表示锁的性质Q如诅R写。fl_flags 是一些标志位Q在 linux 2.6中,q些标志位的定义如下所C:
cd
字段
字段描述
struct file_lock*
fl_next
与烦引节点相关的锁列表中下一个元?
struct list_head
fl_link
指向z跃列表或者被d列表
struct list_head
fl_block
指向锁等待列?
struct files_struct *
fl_owner
锁拥有者的 files_struct
unsigned int
fl_pid
q程拥有者的 pid
wait_queue_head_t
fl_wait
被阻塞进E的{待队列
struct file *
fl_file
指向文g对象
unsigned char
fl_flags
锁标?
unsigned char
fl_type
锁类?
loff_t
fl_start
被锁区域的开始位U?
loff_t
fl_end
被锁区域的结束位U?
struct fasync_struct *
fl_fasync
用于U借暂停通知
unsigned long
fl_break_time
U借的剩余旉
struct file_lock_operations *
fl_ops
指向文g锁操?
struct lock_manager_operations *
fl_mops
指向锁管理操?
union
fl_u
文gpȝ特定信息
清单 2. 标志位的定义
773 #define FL_POSIX 1 774 #define FL_FLOCK 2 775 #define FL_ACCESS 8 /* not trying to lock, just looking */ 776 #define FL_EXISTS 16 /* when unlocking, test for existence */ 777 #define FL_LEASE 32 /* lease held on this file */ 778 #define FL_CLOSE 64 /* unlock on close */ 779 #define FL_SLEEP 128 /* A blocking lock */ |
FL_POSIX 锁是通过pȝ调用 fcntl() 创徏的;?FL_FLOCK 锁是通过pȝ调用 flock()创徏的(详细内容请参见后文中的介l)。FL_FLOCK 锁永q都和一个文件对象相兌Q打开q个文g的进E拥有该 FL_FLOCK 锁。当一个锁被请求或者允许的时候,内核׃把这个进E在同一个文件上的锁都替换掉。FL_POSIX 锁则一直与一个进E以及一个烦引节点相兌。当q程M或者文件描q符被关闭的时候,q个锁会被自动释放?/p>
对于强制锁来_?Linux 中,内核提供?inline 函数 locks_verify_locked() 用于目标文件或者目标文件所在的讑֤是否允许使用强制锁,q且查该讑֤是否已经加上了锁Q相兛_数如下所C:
166 #define __IS_FLG(inode,flg) ((inode)->i_sb->s_flags & (flg)) 173 #define IS_MANDLOCK(inode) __IS_FLG(inode, MS_MANDLOCK) 1047 /** 1048 * locks_mandatory_locked - Check for an active lock 1049 * @inode: the file to check 1050 * 1051 * Searches the inode's list of locks to find any POSIX locks which conflict. 1052 * This function is called from locks_verify_locked() only. 1053 */ 1054 int locks_mandatory_locked(struct inode *inode) 1055 { 1056 fl_owner_t owner = current->files; 1057 struct file_lock *fl; 1058 1059 /* 1060 * Search the lock list for this inode for any POSIX locks. 1061 */ 1062 lock_kernel(); 1063 for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { 1064 if (!IS_POSIX(fl)) 1065 continue; 1066 if (fl->fl_owner != owner) 1067 break; 1068 } 1069 unlock_kernel(); 1070 return fl ? -EAGAIN : 0; 1071 } 1368 /* 1369 * Candidates for mandatory locking have the setgid bit set 1370 * but no group execute bit - an otherwise meaningless combination. 1371 */ 1372 #define MANDATORY_LOCK(inode) \ 1373 (IS_MANDLOCK(inode) && ((inode)->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) 1374 1375 static inline int locks_verify_locked(struct inode *inode) 1376 { 1377 if (MANDATORY_LOCK(inode)) 1378 return locks_mandatory_locked(inode); 1379 return 0; 1380 }
q里Q函?locks_verify_locked() 利用?MANDATORY_LOCK 来检目标文件是否允许加锁,条g包括Q该文g所在的讑֤?super_block l构中的 s_flags 必须被置?1Q该文g?SGID 被置?1 而且同组可执行位被清 0。如果允许,则调用函数l(f)ocks_mandatory_locked()Q该函数从烦引节点的锁列表中查找是否存在有与其相冲突的锁Q即是否已经加上了锁?/p>
![]() ![]() |
q里介绍?Linux 中与文g锁关pd切的两个pȝ调用Qflock() ?fcntl()。劝告锁既可以通过pȝ调用 flock() 来实玎ͼ也可以通过pȝ调用 fcntl() 来实现。flock() pȝ调用是从 BSD 中衍生出来的Q在传统的类 UNIX 操作pȝ中,pȝ调用flock() 只适用于劝告锁。但是,Linux 2.6内核利用pȝ调用 flock() 实现了我们前面提到的Ҏ(gu)的强刉Q共享模式强刉。另外,flock() 只能实现Ҏ(gu)个文件进行加锁,而不能实现记录的加锁。系l调用fcntl() W合 POSIX 标准的文仉实现Q它也是非常强大的文仉Qfcntl() 可以实现对纪录进行加锁?/p>
flock() 的函数原型如下所C:
int flock(int fd, int operation); |
其中Q参?fd 表示文g描述W;参数 operation 指定要进行的锁操作,该参数的取值有如下几种QLOCK_SHQ?LOCK_EXQ?LOCK_UN ?LOCK_MANDphost2008-07-03T00:00:00
man page 里面没有提到Q其各自的意思如下所C:
通常情况下,如果加锁h不能被立xI那么pȝ调用 flock() 会阻塞当前进E。比如,q程惌h一个排他锁Q但此时Q已l由其他q程获取了这个锁Q那么该q程会被阻塞。如果想要在没有获得q个排他锁的情况下不d该进E,可以?LOCK_NB ?LOCK_SH 或?LOCK_EX 联合使用Q那么系l就不会d该进E。flock() 所加的锁会Ҏ(gu)个文件v作用?/p>
fcntl() 函数的功能很多,可以改变已打开的文件的性质Q本文中只是介绍其与获取/讄文g锁有关的功能。fcntl() 的函数原型如下所C:
int fcntl (int fd, int cmd, struct flock *lock); |
其中Q参?fd 表示文g描述W;参数 cmd 指定要进行的锁操作,׃ fcntl() 函数功能比较多,q里先介l与文g锁相关的三个取?F_GETLK、F_SETLK 以及 F_SETLKW。这三个值均?flock l构有关。flock l构如下所C:
struct flock { ... short l_type; /* Type of lock: F_RDLCK, F_WRLCK, F_UNLCK */ short l_whence; /* How to interpret l_start: SEEK_SET, SEEK_CUR, SEEK_END */ off_t l_start; /* Starting offset for lock */ off_t l_len; /* Number of bytes to lock */ pid_t l_pid; /* PID of process blocking our lock (F_GETLK only) */ ... }; |
?flock l构中,l_type 用来指明创徏的是׃n锁还是排他锁Q其取值有三种QF_RDLCKQ共享锁Q、F_WRLCKQ排他锁Q和F_UNLCKQ删除之前徏立的锁)Ql_pid 指明了该锁的拥有者;l_whence、l_start 和l_end q些字段指明了进E需要对文g的哪个区域进行加锁,q个区域是一个连l的字节集合。因此,q程可以对同一个文件的不同部分加不同的锁。l_whence 必须?SEEK_SET、SEEK_CUR ?SEEK_END q几个g的一个,它们分别对应着文g头、当前位|和文g。l_whence 定义了相对于 l_start 的偏U量Ql_start 是从文g开始计的?/p>
可以执行的操作包括:
需要注意的是,F_GETLK 用于试是否可以加锁Q在 F_GETLK 试可以加锁之后QF_SETLK ?F_SETLKW ׃企图建立一把锁Q但是这两者之间ƈ不是一个原子操作,也就是说Q在 F_SETLK 或?F_SETLKW q没有成功加锁之前,另外一个进E就有可能已l插q来加上了一把锁。而且QF_SETLKW 有可能导致程序长旉睡眠。还有,E序Ҏ(gu)个文件拥有的各种锁会在相应的文g描述W被关闭时自动清除,E序q行l束后,其所加的各种锁也会自动清除?/p>
fcntl() 既可以用于劝告锁Q也可以用于强制锁,在默认情况下Q它用于劝告锁。如果它用于强制锁,当进E对某个文gq行了读或写q样的系l调用时Q系l则会检查该文g的锁?O_NONBLOCK 标识Q该标识是文件状态标识的一U,如果讄文g状态标识的时候设|了 O_NONBLOCKQ则该进E会出错q回Q否则,该进E被d。cmd 参数的?F_SETFL 可以用于讄文g状态标识?/p>
此外Q系l调?fcntl() q可以用于租借锁Q此旉用的函数原型如下Q?/p>
int fcntl(int fd, int cmd, long arg); |
与租借锁相关?cmd 参数的取值有两种QF_SETLEASE ?F_GETLEASE。其含义如下所C:
某个q程可能会对文g执行其他一些系l调用(比如 OPEN() 或?TRUNCATE()Q,如果q些pȝ调用与该文g上由 F_SETLEASE 所讄的租借锁相冲H,内核׃dq个pȝ调用Q同Ӟ内核会给拥有q个U借锁的进E发信号Q告知此事。拥有此U借锁的进E会对该信号q行反馈Q它可能会删除这个租借锁Q也可能会减短这个租借锁的租U,从而可以得该文g可以被其他进E所讉K。如果拥有租借锁的进E不能在l定旉内完成上q操作,那么pȝ会强制帮它完成。通过 F_SETLEASE 命o?arg 参数指定?F_UNLCK 可以删除这个租借锁。不对该租借锁减短U约或者干脆删除的操作是进E自愿的q是内核的,只要被阻塞的pȝ调用q没有被发出该调用的q程解除dQ那么系l就会允许这个系l调用执行。即使被d的系l调用因为某些原因被解除dQ但是上面对U借锁减短U约或者删除这个过E还是会执行的?/p>
需要注意的是,U借锁也只能对整个文g生效Q而无法实现记录的加锁?/p>
![]() ![]() |
![]() |
Z使读者更深入理解本文中介l的内容Q下面我们给Z一个例子来详细介绍文g锁的具体用法。这个例子可以用来检所使用的文件是否支持强刉Q其源代码如下所C:
# cat -n mandlock.c 1 #include <errno.h> 2 #include <stdio.h> 3 #include <fcntl.h> 4 #include <sys/wait.h> 5 #include <sys/stat.h> 6 7 int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len) 8 { 9 struct flock lock; 10 11 lock.l_type = type; /* F_RDLCK, F_WRLCK, F_UNLCK */ 12 lock.l_start = offset; /* byte offset, relative to l_whence */ 13 lock.l_whence = whence; /* SEEK_SET, SEEK_CUR, SEEK_END */ 14 lock.l_len = len; /* #bytes (0 means to EOF) */ 15 16 return( fcntl(fd, cmd, &lock) ); 17 } 18 19 #define read_lock(fd, offset, whence, len) \ 20 lock_reg(fd, F_SETLK, F_RDLCK, offset, whence, len) 21 #define write_lock(fd, offset, whence, len) \ 22 lock_reg(fd, F_SETLK, F_WRLCK, offset, whence, len) 23 24 #define err_sys(x) { perror(x); exit(1); } 25 26 int main(int argc, char *argv[]) 27 { 28 int fd, val; 29 pid_t pid; 30 char buf[5]; 31 struct stat statbuf; 32 if (argc != 2) { 33 fprintf(stderr, "usage: %s filename\n", argv[0]); 34 exit(1); 35 } 36 if ((fd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC )) < 0) 37 err_sys("open error"); 38 if (write(fd, "hello world", 11) != 11) 39 err_sys("write error"); 40 41 /* turn on set-group-ID and turn off group-execute */ 42 if (fstat(fd, &statbuf) < 0) 43 err_sys("fstat error"); 44 if (fchmod(fd, (statbuf.st_mode & ~S_IXGRP) | S_ISGID) < 0) 45 err_sys("fchmod error"); 46 47 sleep(2); 48 49 if ((pid = fork()) < 0) { 50 err_sys("fork error"); 51 } else if (pid > 0) { /* parent */ 52 /* write lock entire file */ 53 if (write_lock(fd, 0, SEEK_SET, 0) < 0) 54 err_sys("write_lock error"); 55 56 sleep(20); /* wait for child to set lock and read data */ 57 58 if (waitpid(pid, NULL, 0) < 0) 59 err_sys("waitpid error"); 60 61 } else { /* child */ 62 sleep(10); /* wait for parent to set lock */ 63 64 if ( (val = fcntl(fd, F_GETFL, 0)) < 0) 65 err_sys("fcntl F_GETFL error"); 66 67 val |= O_NONBLOCK; /* turn on O_NONBLOCK flag */ 68 69 if (fcntl(fd, F_SETFL, val) < 0) 70 err_sys("fcntl F_SETFL error"); 71 72 /* first let's see what error we get if region is locked */ 73 if (read_lock(fd, 0, SEEK_SET, 0) != -1) /* no wait */ 74 err_sys("child: read_lock succeeded"); 75 76 printf("read_lock of already-locked region returns %d: %s\n", errno, strerror(errno)); 77 78 /* now try to read the mandatory locked file */ 79 if (lseek(fd, 0, SEEK_SET) == -1) 80 err_sys("lseek error"); 81 if (read(fd, buf, 5) < 0) 82 printf("read failed (mandatory locking works)\n"); 83 else 84 printf("read OK (no mandatory locking), buf = %5.5s\n", buf); 85 } 86 exit(0); 87 } 88 |
样例代码中所采用的技术在前文中大都已l介l过了,其基本思想是在首先在父q程中对文g加上写锁Q然后在子进E中文件描q符讄为非d模式Q第 69 行)Q然后对文g加读锁,q尝试读取该文g中的内容。如果系l支持强刉Q则子进E中?read() pȝ调用Q代码中的第 81 行)会立卌?EAGAINQ否则,{父q程完成写文件操作之后,子进E中?read() pȝ调用׃q回父进E刚刚写入的?5 个字节的数据。代码中的几?sleep() 是ؓ了协调父q程与子q程之间的同步而用的?/p>
该程序在试pȝ的执行结果如下所C:
# mount | grep mnt /dev/sdb7 on /mnt type ext3 (rw,mand) /dev/sdb6 on /tmp/mnt type ext3 (rw) # ./mandlock /mnt/testfile read_lock of already-locked region returns 11: Resource temporarily unavailable read failed (mandatory locking works) # ./mandlock /tmp/mnt/testfile read_lock of already-locked region returns 11: Resource temporarily unavailable read OK (no mandatory locking), buf = hello |
我们可以看到Q?dev/sdb7 使用 –o mand 选项挂蝲C /mnt 目录中,?/dev/sdb6 则么有用这个选项挂蝲C /tmp/mnt 目录中。由于在E序中我们完成了Ҏ(gu)试文?SGID 和同l可执行位的讄Q第 44 行)Q因?/mnt/testfile 可以支持强制锁,?/tmp/mnt/testfile 则不能。这也正是ؓ什么前者的 read() pȝ调用会失败返回而后者则可以成功d?hello 的原因?/p>
![]() ![]() |
![]() |
Linux 的文仉在以׃n索引节点׃n文g的情况下设计的,文g锁的实现可以使得不同用户同时d同一文g的ƈ发问题得以解冟뀂本文描qC Linux 中各cL仉的概念,使用场景Q内怸描述文g锁的数据l构以及与文仉密切相关的系l调用等内容Q至于与文g锁相关的索引节点数据l构Q以及在Ҏ(gu)件进行加锁时遇到的死锁问题等其他知识Q这里没有做详尽介绍Q感兴趣的读者可以自行参考内核源代码?/p>
本文的目的是惛_助读者理?Linux 2.6中文仉的概念以?Linux 2.6 都提供了何种数据l构以及关键的系l调用来实现文g锁,从而可以帮助读者更好地使用文g锁来解决多个q程d同一个文件的互斥问题?/p>
![]() ![]() |
![]() |