Linux1、Linux介绍Linux是类Unix计算机操作系统的统称。Linux操作系统的内核的名字也是“Linux”。Linux这个词本身只表示Linux内核,但在实际上人们已经习惯了用Linux来形容整个基于Linux内核的系统。Linux是由芬兰大学Linus Torvalds于1991年编写的。2、Linux发行版组成Linux内核应用软件一些GNU程序库和工具emacsGCCGNOME命令行shell图形桌面环境KDE(qt编写)GNOME(GTK编写)Unity一些办公软件OpenOffice编译器gccg++文本编辑器到科学工具的应用软件vigedit3、Linux版本商业公司维护的发行版本RedHat(REHL)包管理方式采用基于RPM包的YUM包管理方式社区组织维护的发行版本Debian 包管理方式采用的是:apt-get/dpkg xxx.debRedHat系列RHEL(RedHat Enterprice Linux, 也就是所谓的RedHat Advance Server收费版本),稳定。CentOS(RHEL的社区克隆版本,免费),稳定。FedoraCore(由原来的RedHat桌面版本发展而来,免费版本),稳定性差,最好只用于桌面应用。Debian系列DebianUbuntu命名规则前两位数字:发行时的年份的最后两位数字后两位数字:发行的月份版本桌面版(Desktop):至少三年的技术支持服务器版(Server):至少五年的技术支持LTS版本(Long Term Support)版本发布频率,一年两次主版本号(年份)单数年:短期支持版双数年:长期支持版(LTS)副版本号(月份)四月份(xx.04):该年度的稳定版十月份(xx.10):该年度的测试版学习方法要求记好课堂笔记只听不练学不会Linux,多动手实践课上跟上思路,简单的命令跟着敲,多思考分清主次,重点记忆重要命令资料Linux自带帮助文档 – man鸟哥和私房菜一、文件和目录操作1、基本的shell操作
shell命令行快捷键
编辑命令
Ctrl + a 移到命令行首, ahead,与home键功能相同Ctrl + e 移到命令行尾, end, 与end键功能相同Ctrl + f 按字符前移(右向), forward, 与方向键left功能相同Ctrl + b 按字符后移(左向), back, 与方向键right功能相同Alt + f 按单词前移(右向)Alt + b 按单词后移(左向)Ctrl + xx 在命令行首和光标之间移动Ctrl + u 从光标处删除至命令行首Ctrl + k 从光标处删除至命令行尾Ctrl + w 从光标处删除至字首Alt + d 从光标处删除至字尾Ctrl + d 删除光标处的字符, 与delete键功能相同Ctrl + h 删除光标前的字符, 与backspace键功能相同Ctrl + y 粘贴至光标后, yankAlt + c 从光标处更改为首字母大写的单词Alt + u 从光标处更改为全部大写的单词, uppercaseAlt + l 从光标处更改为全部小写的单词, lowercaseCtrl + t 交换光标处和之前的字符Alt + t 交换光标处和之前的单词Alt + Backspace 与 Ctrl + w 类似,分隔符有些差别
重新执行命令
Ctrl + r 逆向搜索命令历史Ctrl + g 从历史搜索模式退出Ctrl + p 历史中的上一条命令, previous,与方向键up功能相同Ctrl + n 历史中的下一条命令, next, 与方向键down功能相同Alt + . 使用上一条命令的最后一个参数
控制命令
Ctrl + l 清屏, clearCtrl + o 执行当前命令,并选择上一条命令Ctrl + s 阻止屏幕输出Ctrl + q 允许屏幕输出Ctrl + c 终止命令Ctrl + z 挂起命令
Bang (!) 命令
!! 执行上一条命令!blah 执行最近的以 blah 开头的命令,如 !ls!blah:p 仅打印输出,而不执行!$ 上一条命令的最后一个参数,与 Alt + . 相同!$:p 打印输出 !$ 的内容!* 上一条命令的所有参数!*:p 打印输出 !* 的内容^blah 删除上一条命令中的 blah^blah^foo 将上一条命令中的 blah 替换为 foo^blah^foo^ 将上一条命令中所有的 blah 都替换为 foo
虚拟终端(VT)
简介
英文:Virtual Terminal解释:连接在远地的分时共用计算机系统的远程终端,它具有使用户感到是在计算机旁使用终端的功能。
常用工具
XManagerPuttySecureCRT
命令和路径补齐
tab键按一次 当只有一个匹配时,自动补全命令或路径tab键按两次 当有多个匹配时,显示命令或路径列表
2、Linux 标准目录结构
初学Linux,首先需要弄清Linux 标准目录结构:
/ root --- 启动Linux时使用的一些核心文件。如操作系统内核、引导程序Grub等。 home --- 存储普通用户的个人文件 ftp --- 用户所有服务 httpd samba user1 user2 bin --- 系统启动时需要的执行文件(二进制) sbin --- 可执行程序的目录,但大多存放涉及系统管理的命令。只有root权限才能执行 proc --- 虚拟,存在linux内核镜像;保存所有内核参数以及系统配置信息 1 --- 进程编号 usr --- 用户目录,存放用户级的文件 bin --- 几乎所有用户所用命令,另外存在与/bin,/usr/local/bin sbin --- 系统管理员命令,与用户相关,例如,大部分服务器程序 include --- 存放C/C++头文件的目录 lib --- 固定的程序数据 local --- 本地安装软件保存位置 man --- 手工生成的目录 info --- 信息文档 doc --- 不同包文档信息 tmp X11R6 --- 该目录用于保存运行X-Window所需的所有文件。该目录中还包含用于运行GUI要的配置文件和二进制文件。 X386 --- 功能同X11R6,X11 发行版5 的系统文件 boot --- 引导加载器所需文件,系统所需图片保存于此 lib --- 根文件系统目录下程序和核心模块的公共库 modules --- 可加载模块,系统崩溃后重启所需模块 dev --- 设备文件目录 etc --- 配置文件 skel --- home目录建立,该目录初始化 sysconfig --- 网络,时间,键盘等配置目录 var file lib --- 该目录下的文件在系统运行时,会改变 local --- 安装在/usr/local的程序数据,变化的 lock --- 文件使用特定外设或文件,为其上锁,其他文件暂时不能访问 log --- 记录日志 run --- 系统运行合法信息 spool --- 打印机、邮件、代理服务器等假脱机目录 tmp catman --- 缓存目录 mnt --- 临时用于挂载文件系统的地方。一般情况下这个目录是空的。 在我们将要挂载分区时在这个目录下建立目录,再将我们将要访问的设备挂载在这个目录上,这样我们就可访问文件了。 tmp --- 临时文件目录,系统启动后的临时文件存放在/var/tmp lost+found --- 在文件系统修复时恢复的文件
/
根目录,一般根目录下只存放目录,不要存放文件。 /etc、/bin、/dev、/lib、/sbin应该和根目录放置在一个分区中。
/bin, /usr/bin
可执行二进制文件的目录,如常用的命令ls、tar、mv、cat等。
/boot
放置linux系统启动时用到的一些文件。/boot/vmlinuz为linux的内核文件,以及/boot/gurb。建议单独分区,分区大小100M即可。
/dev
存放linux系统下的设备文件,访问该目录下某个文件,相当于访问某个设备,常用的是挂载光驱mount: /dev/cdrom、/mnt
/etc
系统配置文件存放的目录,不建议在此目录下存放可执行文件。 重要的配置文件有:/etc/inittab、/etc/fstab、/etc/init.d、/etc/X11、/etc/sysconfig、/etc/xinetd.d。 修改配置文件之前记得备份。 注:/etc/X11存放与x windows有关的设置。
/home
系统默认的用户家目录,新增用户账号时,用户的家目录都存放在此目录下。 ~表示当前用户的家目录,~test表示用户test的家目录。 建议单独分区,并设置较大的磁盘空间,方便用户存放数据。
/lib,/usr/lib,/usr/local/lib
系统使用的函数库的目录,程序在执行过程中,需要调用一些额外的参数时需要函数库的协助,比较重要的目录为/lib/modules。
/lost+fount
系统异常产生错误时,会将一些遗失的片段放置于此目录下,通常这个目录会自动出现在装置目录下。 如加载硬盘于/disk 中,此目录下就会自动产生目录/disk/lost+found
/mnt,/media
光盘默认挂载点,通常光盘挂载于/mnt/cdrom下,也不一定,可以选择任意位置进行挂载。
/opt
给主机额外安装软件所摆放的目录。 如:FC4使用的Fedora 社群开发软件,如果想要自行安装新的KDE 桌面软件,可以将该软件安装在该目录下。 以前的 Linux 系统中,习惯放置在 /usr/local 目录下。
/proc
此目录的数据都在内存中,如系统核心,外部设备,网络状态,由于数据都存放于内存中,所以不占用磁盘空间。 比较重要的目录有/proc/cpuinfo、/proc/interrupts、/proc/dma、/proc/ioports、/proc/net/*等。
/root
系统管理员root的家目录,系统第一个启动的分区为/,所以最好将/root和/放置在一个分区下。
/sbin,/usr/sbin,/usr/local/sbin
放置系统管理员使用的可执行命令,如fdisk、shutdown、mount等。 与/bin不同的是,这几个目录是给系统管理员root使用的命令,一般用户只能"查看"而不能设置和使用。
/tmp
一般用户或正在执行的程序临时存放文件的目录,任何人都可以访问,重要数据不可放置在此目录下。
/srv
服务启动之后需要访问的数据目录,如www服务需要访问的网页数据存放在/srv/www内。
/usr
应用程序存放目录。 /usr/bin 存放应用程序。 /usr/share 存放共享数据。 /usr/lib 存放不能直接运行的,却是许多程序运行所必需的一些函数库文件。 /usr/local 存放软件升级包。 /usr/share/doc 系统说明文件存放目录。 /usr/share/man 程序说明文件存放目录。 使用 man ls时会查询/usr/share/man/man1/ls.1.gz的内容。 建议单独分区,设置较大的磁盘空间。
/var
放置系统执行过程中经常变化的文件。 /var/log 随时更改的日志文件。 /var/log/message 所有的登录文件存放目录。 /var/spool/mail 邮件存放的目录。 /var/run 程序或服务启动后,其PID存放在该目录下。 建议单独分区,设置较大的磁盘空间。
3、文件和目录操作相关命令用户目录绝对路径:从根目录开始写,如/usr/bin相对路径:相对于当前的工作目录而言. 当前目录.. 当前目录的上一级目录- 在临近的两个目录直接切换root@ubuntu:~#root: 当前用户名@:at, 在ubuntu:主机名~ : 当前用户home目录#:超级用户$:普通用户
ls
ls -al -a, --all 不隐藏任何以. 开始的项目 -l 使用较长格式列出信息-rw-r--r-- 1 super root 3771 6月 7 2016 .bashrcdrwx------ 22 super root 4096 12月 15 08:02 .cachelrwxrwxrwx 1 super root 31 11月 23 07:42 .vimrc -> /home/super/.spf13-vim-3/.vimrc以最后一个为例:lrwxrwxrwx第1个字符:表示文件类型 - 普通文件 d 目录 l 链接符号 b 块设备 c 字符设备 s socket文件 p 管道第2-4个字符:文档所有者权限第5-7个字符:同组用户权限第8-10个字符:其他人权限r: read 4w: write 2x: execute 11 文件的硬链接数super 该文件或目录的所有者root 该文件或目录所属的组31 占用的存储空间11月 23 07:42 文件最后创建或修改的时间.vimrc 文件名
cd
cd ~ 切换到用户home目录cd / 切换到根目录cd 切换到用户home目录cd.. 切换到上一级目录
tree
tree path 显示指定路径的目录树结构
文件或目录颜色一般情况
白色 普通文件蓝色 目录绿色 可执行文件红色 压缩文件青色 链接文件黄色 设备文件灰色 其他文件
mkdir
mkdir dirname 创建目录。mkdir dir1/dir2/dir3 -p 按层次创建目录。
rmdir
rmdir dirname 目录必须为空才能删除,所以实际使用时不常用。
rm
rm -rf dirname 递归强制删除文件夹下的目录和文件,实际使用中常用。rm -ri dirname 递归删除并提示用户删除了哪些目录或文件。
touch
touch test.txt 创建文件。
cp
cp hello.c temp 在当前目录下生成一个temp文件,并把hello.c的内容写入文件。 如果temp不存在,则创建文件;如果存在,则覆盖已有文件。cp mydir newdir -r 在当前目录下生成一个newdir目录,并把mydir目录里面的目录或文件拷贝过去。 如果目录不存在,则创建;如果存在,则mydir目录本身也拷贝到newdir目录下。
cat
cat test.txt 查看文件的内容,缺点内容太多时查看困难。
more
more stdio.h 分屏查看文件,Enter下翻一行,Space下翻一页,缺点不能往回看。
less
less stdio.h 分屏查看文件。比more更实用,可以来回翻页。 ctrl + p 上翻一行 ctrl + n 下翻一行 ctrl + b 上翻一页 ctrl + f 下翻一页 q 退出
head
head -5 stdio.h 查看前五行内容,不加参数默认是10行。
tail
tail -5 stdio.h 查看后5行内容, 不加参数默认是10行。
mv
mv test.c hello.c 移动到。多用于重命名目录或文件。
ln
ln -s ~/.vim/.vimrc .vimrc 创建软链接,相当于windows下的快捷方式,可用于目录或文件。 路径要用绝对路径,这样软链接拷贝到哪里都是有效的。 如果删除原文件,则软链接失效。ln .vimrc .vimrc.hard 创建硬链接,只能用于文件。不必使用绝对路径。 创建后生成的硬链接与原文件引用同一个inode,硬链接本身不占硬盘空间。 如果删除原文件,硬链接仍然有效。
wc
wc test.c 统计文件的行数,字数,字节数。
od
od -tx test.c 以十六进制形式查看文件。od -tc test.c 以ASCII字符形式查看文件。od -td test.c 以有符号十进制形式查看文件。od -tf test.c 以浮点数形式查看文件。od -to test.c 以八进制形式查看文件。od -tu test.c 以无符号十进制形式查看文件。
du
du -h 查看当前文件夹下的目录或文件所占用磁盘的大小。
df
df -h 查看当前文件夹下的目录或文件所使用磁盘空间的详细情况。
which
which ls 查看外部命令的位置,内部命令无法查看。
pwd
pwd 查看当前所在目录
4、文件权限、用户、用户组相关命令
查看当前用户
whoami 查看当前用户名。id 查看当前用户信息,如用户名,所属群组,UID,GID等。
修改目录或文件权限
文字设定法
chmod [who] [+|-|=] [mode]who : 不指定的话,默认是所有 文件所有者:u 文件所属组:g 其他人:o 所有人:amode r : 读 w : 写 x : 执行chmod o+w temp 给其他人加写权限。chmod a-x temp 给所有人去除执行权限。chmod a=r temp 所有人只有读权限。
数字设定法
- 0 没有权限r 4 读w 2 写x 1 执行chmod 755 temp -rwxr-xr-xchmod -001 temp -rwxr-xr--
修改目录或文件所有者与所属组
chown root temp 把文件temp的所有者修改为root。chown super:root temp 把文件temp的所有者修改super,所属组修改为root。
修改目录或文件所属组
chgrp root temp 修改文件所属组为root。
目录必须有执行权限,否则不能打开目录。
5、查找和检索相关命令按文件属性查找
文件名
find ~ -name "hello.c" 按完整名称匹配find ~ -name "*.h" *代表任意长度字符find ~ -name "tem?" ?代表一个任意字符
文件大小
find ~ -size +10k 查找大于10k的文件find ~ -size -10M 查找小于10M的文件find ~ -size +10M -size -100M 查找大于10M小于是100M的文件
文件类型
find ~ -type p 查找类型为管道的档案find ~ -type f 查找类型为文件的档案find ~ -type d 查找类型为目录的档案find ~ -type l 查找类型为链接的档案
按文件内容查找
grep -r "stdio.h" ~ 在用户家目录中查找文件内容里包括stdio.h的所有文件
6、软件安装和卸载在线安装
apt-get
安装 apt-get install tree 在线下载安装移除 apt-get remove tree更新 apt-get update 更新软件列表清理 apt-get clean 清理所有软件安装包,实际上清理的是/var/cache/apt/archives目录下的.deb文件
aptitude
安装 aptitude install tree重新安装 aptitude reinstall tree更新 apt-get update移除 aptitude remove tree显示状态 aptitude show tree
deb包安装
安装
dpkg -i xxx.deb
删除
dpkg -r xxx
源码安装
1)解压缩源代码包。2)进入安装目录。3)检测文件是否缺失,创建Makefile,检测编译环境:./configure。4)编译源码,生成库和可执行程序:make。5)把库和可执行程序,安装到系统目录下:make install。6)删除和卸载软件:make distclean。7)上述安装步骤并不是绝对的,应该先查看附带的README文件。
7、磁盘管理
磁盘设备种类
hd Hard Disk 硬盘fd Floppy Disk 软盘sd SCSI Device 小型计算机系统接口(英语:Small Computer System Interface; 简写:SCSI)。 一种用于计算机和智能设备之间(硬盘、软驱、光驱、打印机、扫描仪等)系统级接口的独立处理器标准。 SCSI是一种智能的通用接口标准。设备都保存在/dev中
sd后面加小写字母,分别代表不同的硬盘,如:
sda 第一个硬盘sdb 第二个硬盘sdc 第三个硬盘sdd 第四个硬盘
每个硬盘又分为主分区和逻辑分区,一个硬盘最多允许四个主分区,第一个逻辑分区从sda5开始。
主分区:sda1 主分区1sda2 主分区2sda3 主分区3sda4 主分区4扩展分区:sda5 逻辑分区1sda6 逻辑分区2sda7 逻辑分区3......
查看设备信息
fdisk -l 当你不知道usb的名称时,可以用这个命令在获取
挂载USB
mount /dev/sdb1 /mnt注: 如果挂载的目录不是一个空目录,则目录里面的内容会被临时覆盖掉,导致目录原有文件无法操作,卸载后会恢复原有文件。建议使用空目录, 如/mnt。
卸载USB
umount /mnt
二、打包压缩和常用服务器1、压缩包管理屌丝版
gzip — .gz格式压缩包
gzip *.txt 假设当前目录中有a.txt和b.txt, 则会生成a.txt.gz和b.txt.gz,txt源文件会被删除。 这个命令不能用于目录。gunzip *.gz 解压
bzip2 — .bz2格式的压缩包
bzip2 -k *.txt 假设当前目录中有a.txt和b.txt,则会生成a.txt.bz2和b.txt.bz2文件,加-k参数可以将源文件保留。 这个命令不能用于目录。bunzip2 *.bz2 解压
高富帅版tar — 不使用z或j参数,该命令只能对文件和目录打包
参数
c 创建--压缩时使用。x 释放--解压缩时使用。v 显示提示信息--压缩和解压缩都可以使用,可以省略。f 指定压缩文件的名字z 使用gzip的方式压缩文件j 使用bzip2的方式压缩文件
压缩
用法:tar zcvf 生成的压缩包的名字(xxx.tar.gz) 要压缩的文件或目录示例:tar zcvf alltxt.tar.gz *.txt test/ 同时对文件和目录进行打包压缩用法:tar jcvf 生成的压缩包的名字(xxx.tar.bz2) 要压缩的文件或目录示例:tar jcvf alltxt.tar.bz2 *.txt test/ 同时对文件和目录进行打包压缩
解压缩
tar zxvf 压缩包的名字 解压到当前目录tar jxvf 压缩包的名字 -C 目录 解压到指定目录
rar
参数
a Add压缩x Extract解压缩r 压缩时递归目录,不加这个参数默认就是递归的
压缩
用法:rar a 生成的压缩文件的名字 压缩的文件或目录示例:rar a all *.txt 打包压缩文件rar a dir dir/ 打包压缩目录
解压缩
用法:rar x 压缩文件名 [解压缩目录]示例:rar x all.rar
zip
参数
r 压缩目录时加个参数用于递归目录,不加不能压缩
压缩
用法:zip 压缩包的名字 压缩的文件或目录示例:zip all *.txt zip -r myzip mytest/
解压缩
用法:unzip 压缩包的名字 unzip 压缩包的名字 -d 解压的目录示例:unzip all.zip unzip all.zip -d test/
2、进程管理
查看在线用户状态
who 查看当前在线用户的状态tty1~tty6 文字界面终端tty7 图形界面终端pts 虚拟终端Alt+Ctrl+F1~F7 切换终端,切换后各个终端互不影响
查看进程
ps aux 查看在线用户下所有进程ps aux | grep bash 进程过滤
终止进程
kill -l 查看所有信号kill -SIGKILL 5179 终止进程kill -9 4678 终止进程
查看当前进程的环境变量
env 查看所有环境变量env | grep PATH 只查看PATH环境变量
查看系统状态
top
3、网络管理
获取网络接口信息
ifconfig
测试与目标主机连通性
ping www.baidu.com -c 4 发送4个数据包后终止
查看服务器域名对应的IP地址
nslookup www.baidu.com
4、用户管理
创建用户
adduser super 用户名只能小写,不能大写useradd -s /bin/bash -g super -d /home/super -m super 用户名可以大写-s 指定新用户登陆时shell类型-g 指定所属组,该组必须已经存在-d 用户家目录-m 用户家目录不存在时,自动创建该目录
设置用户组
groupadd super
删除用户
deluser superuserdel -r super 选项-r的作用是把用户的主目录一起删除
切换用户
su super
修改用户密码
passwd super
退出当前用户
exit
查看所有用户信息
vi /etc/passwd
5、ftp服务器搭建vsftpd作用:文件的上传和下载服务器端
安装vsftpd
apt-get install -y vsftpd 安装完成后会随系统启动而自动启动
修改配置文件
vi /etc/vsftpd.conflisten=YESanon_root=/home/super/anonFtp/ #指定匿名用户根目录,不指定默认是/srv/ftp/anonymous_enable=YES #允许匿名用户登录write_enable=YES #实名用户拥有写权限(上传数据)local_umask=022 #设置本地掩码为022anon_upload_enable=YES #匿名用户可以向ftp服务器上传数据anon_mkdir_write_enable=YES #匿名用户可以在ftp服务器上创建目录
创建匿名用户根目录
cd ~mkdir anonFtpchown ftp anonFtpchmod 777 anonFtp
重启服务
service vsftpd retart
客户端
实名用户登录
ftp IP(server)输入用户名输入密码文件的上传和下载 文件的上传: put file 文件的下载: get file 不允许操作目录,如果想操作目录 -- 打包tar/rar/zip
匿名用户登录
ftp IP(server)用户名:anonymous密码:直接回车不允许匿名用户在任意目录直接切换只能在一个指定目录范围内工作需要在ftp服务器上创建一个匿名用户的目录 -- 匿名用户的根目录
退出
quit 推荐bye 推荐exit
lftp客户端访问ftp服务器
一个ftp客户端工具,可以上传和下载目录
安装
apt-get install -y lftp
登录服务器
匿名
lftp IP(sever) 回车login
实名
lftp username@IP(sever) 回车输入服务器密码
操作
put file 上传文件mput file1 file2 上传多个文件get file 下载文件mget file1 file2 下载多个文件mirror dir 下载整个目录及其子目录mirror -R dir 上传整个目录及其子目录
6、nfs服务器搭建net file system : 网络文件系统,它允许网络中的计算机之间通过TCP/IP网络共享资源。服务器端
安装
apt-get install nfs-kernel-server 安装成功后会随系统启动而自动启动
创建共享目录
如: /home/super/NfsShare
修改配置文件
vi /etc/exports在文件最后加入下面设置:/home/super/NfsShare *(rw, sync)
重启服务
service nfs-kernel-server restart
客户端
挂载服务器共享目录
用法: mount serverIP:ShareDir /mnt示例: mount 192.168.10.100:/home/super/NfsShare /mnt
7、ssh(Secure Shell)服务器服务器端
安装ssh
apt-get install -y openssh-serveraptitude show openssh-server
客户端
远程登录
ssh Username@ServerIP
退出登录
logout
8、scp(Super Copy)命令
使用该命令的前提条件
目标主机已经安装了openssh-server
使用方法
scp -r 目标用户名@目标主机IP地址:/目标文件的绝对路径 /保存到本机的绝对(相对)路径scp -r super@192.168.10.100:/home/super/SCP/ ./mydir/
9、其他命令
翻页
Shift+PageUp 上翻页Shift+PageDown 下翻页
清屏
clearCtrl+l
创建终端
Ctrl+Alt+T UbuntuCtrl+Shift+T 添加新标签页
看手册
man man一共有九个章节,1,2,3,5是重点:1 可执行程序或 shell 命令2 系统调用(内核提供的函数)3 库调用(程序库中的函数)4 特殊文件(通常位于 /dev)5 文件格式和规范,如 /etc/passwd6 游戏7 杂项(包括宏包和规范,如man(7),groff(7))8 系统管理命令(通常只针对root用户)9 内核例程 [非标准
设置查看别名
alias 查看alias l='ls -al' 设置
在显示器上显示数据
echo "hello" 打印字符串echo $PATH 打印环境变量echo $? 显示上一次程序退出值
10、关机重启poweroffrebootshutdown
参数
-t 秒数:设定在切换至不同的runlevel之前,警告和删除两讯号之间的延迟时间(秒)-k 仅送出警告讯息文字,但不是真的要shutdown-r shutdown之后重新开机-h shutdown之后关机-n 不经过init,由shutdown指令本身来做关机动作(不建议使用)-f 重新开机时,跳过fsck指令,不检查档案系统-F 重新开机时,强迫做fsck检查-c 将已经正在shutdown的动作取消
示例
shutdown -r now #立即重启shutdown -h now #立即关机shutdown -k now 'Hey! Go away! now...' #发出警讯息,但没有真的关机shutdown -t3 -r now #立即重启,但在警告和删除processes之间,延迟3秒钟shutdown -h 10:42 'Hey! Go away!' #10:42关机shutdown -r 10 'Hey! Go away!' #10分钟后关机shutdown -c #取消shutdown指令,必须切换至其他tty,登入之后,才能下些命令shutdown now #切换至单人操作模式(不加任何选项时)
三、vim和函数库1、vim编辑器的使用1.1、vim简介Vim是从 vi 发展出来的一个文本编辑器。代码补全、编译及错误跳转等方便编程的功能特别丰富,在程序员中被广泛使用,和Emacs并列成为类Unix系统用户最喜欢的文本编辑器。1.2、工作模式命令模式 — 打开文件之后,默认进入命令模式。
移动光标
h 左j 下k 下l 右0 行首$ 行尾gg 文件头部G 文件尾部5G 行跳转,移到第五行
删除操作(不是真正意义上的删除,更象是剪切操作)
x 删除光标后一个字符X 删除光标前一个字符dw 删除光标后一个单词d0 删除光标到行首的所有字符D(d$) 删除光标到行尾的所有字符dd 删除一行5dd 删除五行
撤消操作
u 撤消ctrl+r 还原前一个操作
复制粘贴
p 小写的p,粘贴到光标的下一行P 大写的p,粘贴到光标的所在行yy 复制一行5yy 复制五行
可视模式
v 切换到可视块模式h/j/k/l 调整选中块y 复制d 删除p 粘贴
查找模式
/ 切换到查找模式,向下查找? 切换到查找模式,向上查找n 下一个匹配N 上一个匹配# 移到要查找的单词上,按#号即可开启查找模式
字符替换
r 单个字符替换
行缩进
>> 向右缩进<< 向左缩进
查看函数man文档
K 先输入3(库函数章节),再输入K,以查看指定函数的man文档
编辑模式 — 需要输入一些命令,切换到编辑模式。
a 在光标所在位置的后边插入A 在当前行的尾部插入i 在光标所在位置的前边插入I 在光标所在行的行首插入o 在光标所在行的下边开辟一个新的行O 在光标所在行的上边开辟一个新的行s 删除光标后边的字符S 删除光标所有的行
末行模式 — 在末行模式下可以输入一些命令。
:s/tom/jack/g 把光标所在行的tom替换成jack:%s/tom/jack/g 把整个文档的tom替换成jack:25,30s/tom/jack/g 把25到30行的tom替换成jack:q 退出:q! 强制退出:w 保存:wq 保存并退出:x 相当于:wqZZ 相当于:wq
分屏操作
:sp [file] 将屏幕水平分成两部分:vsp [file] 交屏幕垂直分成两部分:wqall 同时保存打开文件ctrl+ww 切换两个屏幕
vim打造成IDE
/etc/vim/vimrc 系统级配置文件~/.vim/vimrc 用户级配置文件
2、gcc编译器
gcc编译的四个阶段:
hello.c --------> hello.i --------> hello.s --------> hello.o -------> hello.out 预处理编译器(cpp) 编译器(gcc) 汇编器(as) 链接器(ld) gcc -E gcc -S gcc -c gcc
编译工具链:
预处理编译器:cpp gcc -E hello.c -o hello.i 头文件展开,宏替换,注释去掉 编译器:gcc gcc -S hello.i -o hello.s c文件变成汇编文件 汇编器:as gcc -c hello.s -o hello.o 汇编文件变成二进制文件 链接器:ld gcc hello.o -o hello 将函数库中相应的代码组合到目标文件中
直接编译生成可执行文件
gcc hello.c -o hello
编译时指定头文件目录-I
gcc hello.c -I ./include hello
编译时指定宏,通常用于调试代码-D
gcc hello.c -D DEBUG在需要打印日志的代码中加上下面的语句:#ifdef DEBUG printf("debug info");#endif
编译时对代码进行优化-O3
gcc hello.c -o hello -O3 级别:0 没有优化1 缺省值3 优化级别最高
编译时显示告警信息-Wall
gcc hello.c -o hello -Wall
编译时包含调试信息-g(gdb)
gcc hello.c -o hello -g
查看编译版本
gcc -vgcc --version
3、静态库的创建和使用
准备
目录结构myCalc├── include│?? └── head.h├── lib│?? └── libMyCalc.a├── main.c└── src ├── add.c ├── div.c ├── mul.c ├── sub.c
命名格式以lib
开头。静态库名。
.a
结尾。
示例 : libMyCalc.a
描述优点寻址方便、速度快。库被打包到可执行程序中,直接发布可执行程序即可使用。缺点静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。如果静态函数库改变了,那么你的程序就必须重新编译。使用场合在核心程序上使用,保证速度,忽略空间。主流应用于80、90年代,现在很少使用。制作
得到与位置有关的*.o
cd ~/myClac/srcgcc *.c -c -I ../include
将生成的*.o
文件打包成静态库libMyCalc.a
ar rcs libMyCalc.a *.oar工具不包含在一gcc中。参数:r 将文件夹插入到静态库中。c 创建静态库,不管库是否存在。s 写入一个目标文件索引到库中,或者更新一个存在的目标文件。制作好以后移动到lib目录中mv libMyCalc.a ../lib
查看库中的符号(函数)
nm libMyCalc.a
发布和使用静态库发布静态库,把include
和lib
目录打包给用户。使用
在main.c
中包含头文件
#inlcude "head.h"
两种编译方式
gcc main.c lib/libMyCalc.a -I include -o myappgcc main.c -I include -L lib -l MyCalc -o myapp
执行myapp
./myapp
4、动态库的创建和使用
准备
目录结构myCalc├── include│?? └── head.h├── lib│?? └── libMyCalc.so├── main.c└── src ├── add.c ├── div.c ├── mul.c ├── sub.c
命名格式以lib
开头。静态库名。
.so
结尾。
示例 : libMyCalc.so
描述优点执行程序体积小。动态库更新了,不需要重新编译程序,前提是函数接口不变。缺点发布程序的时候,需要将动态库提供给用户。动态库没有被打包到应用程序中,加载速度相对较慢。使用场合现代应用程序中常用。制作
生成与位置无关的*.o
cd ~/myClac/srcgcc -fPIC *.c -c -I ../include
将生成的*.o
文件打包成共享库(动态库)libMyCalc.so
gcc -shared -o libMyCalc.so *.o -I ../include制作好以后移动到lib目录中mv libMyCalc.so ../lib
查看库中的符号(函数)
nm libMyCalc.so
发布和使用静态库发布静态库,把include
和lib
目录打包给用户。使用
在main.c
中包含头文件
#inlcude "head.h"
两种编译方式
gcc main.c lib/libMyCalc.so -I include -o myappgcc main.c -I include -L lib -l MyCalc -o myapp
执行myapp
./myapp
查看可执行文件夹所依赖的动态库
ldd myapp
解决依赖的动态库无法加载的问题
把libMyCalc.so
拷贝到/lib
目录下(不推荐使用,容易与系统库冲突)
cp lib/libMyCalc.so /lib
设置环境变量LD_LIBRARY_PATH(测试时使用)
export LD_LIBRARY_PATH=./lib 只对当前会话有效
设置环境变量LD_LIBRARY_PATH到~/.bashrc中(测试时使用)
vi ~/.bashrcexport LD_LIBRARY_PATH=/home/super/myCalc/lib 会话每次开启就会生效
设置配置文件/etc/ld.so.conf
(推荐使用),重启终端
编辑动态连接器的配置文件
vi /etc/ld.so.conf
动态库的路径写到配置文件中
/home/super/myCalc/lib
更新动态库
ldconfig -v
四、makefile和文件IO1、gdb调试
1.1、启动gdb
gdb app
1.2、查看代码
>>>(gdb) l #list>>>(gdb) l 行号或函数名>>>(gdb) l 文件名:行号或函数名
1.3、设置断点
设置当前文件断点
>>>(gdb) b #break>>>(gdb) b 行号或函数名>>>(gdb) b 文件名:行号或函数名
设置条件断点
>>>(gdb) b 10 if value==19
删除断点
>>>(gdb) d 断点的编号 #delete或del
1.4、查看设置的断点
>>>(gdb) i b #info, 可以获取断点的编号,删除断点时用
1.5、开始执行gdb调试
>>>(gdb) start #只执行一步>>>(gdb) c #continue,直接停在断点的位置>>>(gdb) run #有断点会停在断点处,没有会直接跑完程序,较少用
1.6、单步调试
>>>(gdb) s #进入函数体内部>>>(gdb) finish #从函数体内部跳出>>>(gdb) n #不进入函数体内部>>>(gdb) u #退出当前循环
1.7、查看变量的值
>>>(gdb) p print
1.8、查看变量的类型
>>>(gdb) ptype 变量名
1.9、设置变量的值
>>>(gdb) set var 变量=值
1.10、设置追踪变量
>>>(gdb) display 变量 #设置追踪变量>>>(gdb) info display #获取变量的编号>>>(gdb) undisplay 编号 #取消追踪变量
1.10、退出gdb调试
>>>(gdb) quit
2、makefile的编写2.1、makefile的命名
makefile Makefile 注:两种任选其中一种,其他名称不行。
2.2、makefile的规则规则中的三要素:目标、依赖、命令
makefile文件内容格式
目标:依赖文件 命令
makefile文件内容简单示例
app:main.c add.c sub.c mul.c div.c gcc main.c add.c sub.c mul.c div.c -o app
第二行必须有一个tab缩进。
子目标和终极目标
示例
#终极目标app:main.o add.o sub.o div.o gcc main.o add.o sub.o div.o -o app#子目标main.o:main.c gcc -c main.c#子目标add.o:add.c gcc -c add.c#子目标sub.o:sub.c gcc -c sub.c#子目标mul.o:mul.c gcc -c mul.c#子目标div.o:div.c gcc -c div.c
好处当其他一个文件被修改时,只会编译修改的文件,再打包生成app,编译效率高。更新目标的原则2.3、makefile的两个函数wildcard
:取得目录下的所有文件patsubst
:将目标下的所有文件作替换
示例
#自定义变量src=$(wildcard ./*.c)obj=$(patsubst ./%.c, ./%.o, $(src))target=app#终极目标$(target):$(obj) gcc $(obj) -o $(target)#子目标%.o:%.c gcc -c $< -o $@
2.4、makefile的三个自动变量普通变量变量取值:foo = $(obj)
由makefile维护的一些变量通常格式都是大写CC
: 默认值是cc
有些有默认值,有些没有CPPFLAGS
: 预处理器需要的选项,如:-I
CFLAGS
: 编译的时候使用的参数 -Wall -g -c
LDFLAGS
: 链接库使用的选项 -L -l
用户可以修改这些变量的默认值CC = gcc
自动变量变量$<
规则中的第一个依赖条件$@
规则中的目标$^
规则中的所有依赖条件以上三种变量只能在规则的命令中使用模式规则在规则的目标定义中使用%在规则的依赖条件中使用%
示例
#自定义变量src=$(wildcard ./*.c)obj=$(patsubst ./%.c, ./%.o, $(src))target=app#makefile维护的变量CC = gccCPPFLAGS = -I#终极目标$(target):$(obj) $(CC) $^ -o $@#子目标%.o:%.c $(CC) -c $< -o $@#伪目标.PHONY:cleanclean: #命令前面加-表示,如果命令执行失败则忽略这个命令 -makir /release rm -f $(obj) $(target)
3、系统IO函数3.1、一些概念
C库IO函数工作流程
虚拟内存地址空间
pcb与文件描述符
库函数与系统函数之间的关系
CPU为什么要使用虚拟地址空间与物理地址空间映射?解决了什么问题?方便编译器和操作系统安排程序的地址分布。程序可以使用一系列相邻的虚拟地址来访问物理内存中不相邻的大内存缓冲区方便进程之间隔离不同进程使用的虚拟地址彼此隔离,一个进程中的代码无法更改正在由另一个进程使用的物理内存。方便OS使用你那可怜的内存程序可以使用一系列虚拟地址来访问大于可用物理内存的内存缓冲区。当物理内存的供应量变小时,内存管理器会将物理内存页(通常大小为4KB)保存到磁盘文件。数据或代码页会根据需要在物理内存和磁盘之间移动。
查看帮助文档
man 2 openman 3 printf
errno定义在头文件/usr/include/error.h
中全局变量任何标准C库函数都能对其进行修改(Linux系统函数更可以)错误宏定义位置第1-34个错误定义:/usr/include/asm-generic/errno-base.h
第35-133个错误定义:/usr/include/asm-generic/errno.h
是记录系统的最后一次错误代码。代码是一个int型的值。第个errno值对应着以字符串表示的错误类型。当调用“某些”函数出错时,该函数会重新设置errno的值。perror函数头文件stdio.h
函数定义void perror(const char * s)
函数说明用来将上一个函数发生的错误的原因输出到标准设备(stderr)。参数s所指的字符串会先打印出,后面再加上错误原因字符串。些错误原因依照全局变量error的值来决定要输出的字符串。3.2、open
函数定义
int open(const char *pathname, int flags);int open(const char *pathname, int flags, mode_t mode);
功能
打开文件。
参数
pathname 文件路径,如./hello.cflags 文件访问模式,O_RDONLY, O_WRONLY, O_RDWR, 更多见man 2 openmode 文件权限设置,实际结果是mode & umask
返回值
返回一个文件描述fd,-1表示打开文件时发生错误。
示例
#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>#include <stdio.h>int main(){ int fd; //打开文件 fd = open("hello.c", O_RDWR); //打开文件,不存在则创建并设置权限为:755 & umask fd = open("hello.c", O_RDWR | O_CREAT, 0755); //打开文件,不存在则创建并设置权限为:755 & umask,另判断文件是否存在 fd = open("hello.c", O_RDWR | O_CREAT | O_EXCL, 0755); //打开文件并清空文件里的内容 fd = open("hello.c", O_RDWR | O_TRUNC); printf("fd = %d\n", fd); //打开失败则打印错误并退出程序 if(fd == -1) { perror("open file failure"); exit(1); } int ret = close(fd); printf("ret = %d\n", ret); //关闭失败则打印错误并退出程序 if(ret == -1) { perror("close file failure"); exit(1); } return 0;}
3.3、read
函数定义
ssize_t read(int fd, void *buf, size_t count);
功能
读取文件。
参数
fd 文件描述符buf 缓冲区count 读取多少字节数
返回值
有符号int型值-1 表示读文件失败0 表示文件读完了>0 表示读取的字节数
3.4、write
函数定义
ssize_t write(int fd, const void *buf, size_t count);
功能
写入文件。
参数
fd 文件描述符buf 缓冲区count 读取多少字节数
返回值
有符号int型值-1 表示写文件失败0 表示什么都没写>0 表示写了多少字节数
示例
#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>int main(){ //以只读方式找开文件 int fd = open("english.txt", O_RDONLY); if(fd == -1) { perror("open"); exit(1); } //以写的方式找开文件,文件不存在则创建 int fd1 = open("newfile", O_CREAT | O_WRONLY, 0664); //打开失败,打印错误并退出程序 if(fd1 == -1) { perror("open1"); exit(1); } char buf[2048] = {0}; //每次读取2048字节 int count = read(fd, buf, sizeof(buf)); //读取失败,打印错误并退出程序 if(count == -1) { perror("read"); exit(1); } while(count) { //写入文件 int ret = write(fd1, buf, count); printf("write bytes %d\n", ret); //继续读取内容 count = read(fd, buf, sizeof(buf)); } //关闭文件 close(fd); close(fd1); return 0;}
3.5、close
函数定义
int close(int fd);
功能
关闭文件。
参数
fd 文件描述符
返回值
0 表示关闭成功-1 表示关闭失败
3.6、lseek
函数定义
off_t lseek(int fd, off_t offset, int whence);
功能
1、获取文件大小。2、移动文件指针。3、文件拓展。
参数
fd 文件描述符offset 文件指针偏移量whence 来源,主要值有:SEEK_SET、SEEK_CUR、SEEK_END等
返回值
有符号int型值-1 表示读文件失败0 表示文件读完了>0 表示读取的字节数
示例
#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>int main(){ int fd = open("aa", O_RDWR); if(fd == -1) { perror("open file"); exit(1); } int ret = lseek(fd, 0, SEEK_END); printf("file length = %d\n", ret); //文件拓展 ret = lseek(fd, 2000, SEEK_END); printf("return value = %d\n", ret); //实现文件拓展,需要再最后做一次写操作 write(fd, "a", 1); close(fd); return 0;}
五、一些系统函数的使用1、Linux文件操作相关函数stat函数
函数定义
int stat(const char *pathname, struct stat *buf);
功能
获取文件属性(从inode上获取)。
参数
pathname 文件名buf 结构体指针stat
返回值
0 成功-1 失败
文件属性
struct stat { dev_t st_dev; /* 文件的设备编号 */ ino_t st_ino; /* 节点 */ mode_t st_mode; /* 文件的类型和存取的权限 */ nlink_t st_nlink; /* 链接到该文件的硬链接数目,刚建立的文件值为1 */ uid_t st_uid; /* 用户ID */ gid_t st_gid; /* 组ID */ dev_t st_rdev; /* (设备类型)若此文件为设备文件,则为其设备编号 */ off_t st_size; /* 文件字节数(文件大小) */ blksize_t st_blksize; /* 块大小(文件系统的I/O, 缓冲区的大小) */ blkcnt_t st_blocks; /* 块数 */ struct timespec st_atim; /* 最后一次访问时间 */ struct timespec st_mtim; /* 最后一次修改时间 */ struct timespec st_ctim; /* 最后一次改变时间(属性) */}
特性能够穿透(跟踪)符号链接。如果是软链接,会统计原始文件信息,而不是软链接的信息。
示例
#include <sys/types.h>#include <sys/stat.h>#include <stdlib.h>#include <time.h>#include <pwd.h>#include <grp.h>int main(int argc, char * argv[]){ if(argc < 2) { printf("./a.out filename\n"); exit(1); } struct stat st; int ret = stat(argv[1], &st); if(ret == -1) { perror("stat"); exit(1); } //存储文件类型和访问权限 char perms[11] = {0}; //判断文件类型 switch(st.st_mode & S_IFMT) { case S_IFLNK: perms[0] = 'l'; break; case S_IFDIR: perms[0] = 'd'; break; case S_IFREG: perms[0] = '-'; break; case S_IFBLK: perms[0] = 'b'; break; case S_IFCHR: perms[0] = 'c'; break; case S_IFSOCK: perms[0] = 's'; break; case S_IFIFO: perms[0] = 'p'; break; default: perms[0] = '?'; break; } //判断文件的访问权限 //文件所有者 perms[1] = (st.st_mode & S_IRUSR) ? 'r' : '-'; perms[2] = (st.st_mode & S_IWUSR) ? 'w' : '-'; perms[3] = (st.st_mode & S_IXUSR) ? 'x' : '-'; //文件所属组 perms[4] = (st.st_mode & S_IRGRP) ? 'r' : '-'; perms[5] = (st.st_mode & S_IWGRP) ? 'w' : '-'; perms[6] = (st.st_mode & S_IXGRP) ? 'x' : '-'; //其他人 perms[7] = (st.st_mode & S_IROTH) ? 'r' : '-'; perms[8] = (st.st_mode & S_IWOTH) ? 'w' : '-'; perms[9] = (st.st_mode & S_IXOTH) ? 'x' : '-'; //硬链接计数 int linkNum = st.st_nlink; //文件所有者 char * fileUser = getpwuid(st.st_uid)->pw_name; //文件所属组 char * fileGrp = getgrgid(st.st_gid)->gr_name; //文件大小 int filesize = (int)st.st_size; //修改时间 char * time = ctime(&st.st_mtime); char mtime[512] = {0}; strncpy(mtime, time, strlen(time) - 1); char buf[1024]; sprintf(buf, "%s %d %s %s %d %s %s", perms, linkNum, fileUser, fileGrp, fileSize, mtime, argv[1]); printf("%s\n", buf); return 0;}
st_mode该变量占两字节,共16位。掩码的使用:st_mode & 掩码
其他人权限(0-2 bit)
S_IROTH 00004 读权限S_IWOTH 00002 写权限S_IXOTH 00001 执行权限S_IRWXO 00007 掩码
所属组权限(3-5 bit)
S_IRGRP 00040 读权限S_IWGRP 00020 写权限S_IXGRP 00010 执行权限S_IRWXG 00070 掩码
文件所有者权限(6-8 bit)
S_IRUSR 00400 读权限S_IWUSR 00200 写权限S_IXUSR 00100 执行权限S_IRWXU 00700 掩码
特殊权限位(9-11 bit),很少用
S_ISUID 0004000 设置用户IDS_ISGID 0002000 设置组IDS_ISVTX 0001000 黏住位
文件类型(12-15 bit)
S_IFSOCK 0140000 套接字S_IFLNK 0120000 符号链接(软链接)S_IFREG 0100000 普通文件S_IFBLK 0060000 块设备S_IFDIR 0040000 目录S_IFCHR 0020000 字符设备S_IFIFO 0010000 管道S_IFMT 0170000 掩码
lstat函数功能和用法与stat相同特性:不穿透(跟踪)符号链接。如果是软链接,会统计软链接的信息,而不是原始文件的信息。链接的追踪access函数
函数定义
int access(const char *pathname, int mode);
功能
测试指定文件是否拥有某种权限。
参数
pathname 文件名mode 权限类别 R_OK 是否有读权限 W_OK 是否有写权限 X_OK 是否有执行权限 F_OK 测试一个文件是否存在
返回值
0 所有欲查核的权限都通过了检查-1 有权限被禁止
示例
#include <stdio.h>#include <stdlib.h>#include <unistd.h>int main(int argc, char * argv[]){ if(argc < 2) { printf("access filename\n"); exit(1); } int ret = access(argv[1], W_OK); if(ret == -1) { perror("access"); exit(1); } printf("you can write this file.\n"); return 0;}
chmod函数
函数定义
int chmod(const char *pathname, mode_t mode);
功能
改变文件的权限
参数
pathname 文件名mode 权限,必须是一个8进制数字,转换用strtol函数
返回值
0 改变成功-1 失败
示例
#include <stdio.h>#include <stdlib.h>#include <sys/stat.h>int main(int argc, char * argv[]){ if(argc < 2) { printf("chmod filename\n"); exit(1); } int ret = chmod(argv[1], 0755); if(ret == -1) { perror("chmod"); exit(1); } return 0;}
chown函数
函数定义
int chown(const char *pathname, uid_t owner, gid_t group);
功能
改变文件的所有者
参数
pathname 文件名owner 文件所有者IDgroup 文件所属组ID查看UID和GID:/etc/passwd
返回值
0 成功-1 失败
示例
#include <stdio.h>#include <stdlib.h>#include <unistd.h>int main(int argc, char * argv[]){ if(argc < 2) { printf("chown filename\n"); exit(1); } int ret = chown(argv[1], 116, 125); if(ret == -1) { perror("chown"); exit(1); } return 0;}
truncate函数
函数定义
int truncate(const char *path, off_t length);
功能
将参数path指定的文件大小改为参数length指定的大小。如果原来的文件大小比参数length大,则超过部分会被删去。
参数
path 文件路径length 指定文件的大小
返回值
0 成功-1 失败
连接函数link函数
函数定义
int link(const char *oldpath, const char *newpath);
功能
创建一个硬链接。
symlink函数
函数定义
int symlink(const char *target, const char *linkpath);
功能
创建一个软链接。
readlink函数
函数定义
ssize_t readlink(const char *pathname, char *buf, size_t bufsiz);
功能
读软链接对应的文件名,而不是读内容。
示例
#include <stdio.h>#include <stdlib.h>#include <unistd.h>int main(int argc, char * argv[]){ if(argc < 2) { printf("readlink filename\n"); exit(1); } char buf[512]; int ret = readlink(argv[1], buf, sizeof(buf)); if(ret == -1) { perror("readlink"); exit(1); } buf[ret] = 0; printf("buf = %s\n", buf); return 0;}
unlink函数
函数定义
int unlink(const char *pathname);
功能
删除一个文件的目录并减少它的链接数,若成功则返回0,否则返回-1,错误原因存于errno。如果想调用这个函数来成功删除文件,你就必须拥有这个文件的所属目录的写和执行权限。
使用
如果是符号链接,删除符号链接。如果是硬链接,硬链接数减1,,当减为0时,释放数据块和inode。如果文件硬链接数为0,但有进程已打开该文件,并持有文件描述符,则等该进程关闭该文件时,kernel才真正去删除该文件。
示例
#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <fcntl.h>int main(){ int fd = open("tempfile", O_CREAT | O_RDWR, 0664); if(fd == -1) { perror("open"); exit(1); } //删除临时文件 int ret = unlink("tempfile"); //write file write(fd, "hello\n", 5); //重置文件指针 lssek(fd, 0, SEEK_SET); //read file char buf[24] = {0}; int len = read(fd, buf, sizeof(buf)); //将读出的内容写在屏幕上 write(1, buf, len); //close file close(fd); return 0;}
rename函数
函数定义
int rename(const char *oldpath, const char *newpath);
功能
文件重命名。
2、Linux目录操作相关函数chdir函数
函数定义
int chdir(const char *path);
功能
修改当前进程的路径。
getcwd函数
函数定义
char *getcwd(char *buf, size_t size);
功能
获取当前进程工作目录。
mkdir函数
函数定义
int mkdir(const char *pathname, mode_t mode);
功能
创建目录。注意:创建的目录需要有执行权限,否则无法进入目录。
rmdir函数
函数定义
int rmdir(const char *pathname);
功能
删除一个空目录。
opendir函数
函数定义
DIR *opendir(const char *name);
功能
打开一个目录。
readdir函数
函数定义
struct dirent *readdir(DIR *dirp);
功能
读目录。
返回值
struct dirent { ino_t d_ino; /* 此目录进入点的inode */ off_t d_off; /* 目录文件开头至此目录进入点的位移 */ unsigned short d_reclen; /* d_name的长度,不包含NULL字符 */ unsigned char d_type; /* d_name所指的文件类型 */ char d_name[256]; /* 文件名 */};d_type:DT_BLK This is a block device.DT_CHR This is a character device.DT_DIR This is a directory.DT_FIFO This is a named pipe (FIFO).DT_LNK This is a symbolic link.DT_REG This is a regular file.DT_SOCK This is a UNIX domain socket.DT_UNKNOWN The file type is unknown.-D_BSD_SOURCE 编译时添加宏定义
colsedir函数
函数定义
int closedir(DIR *dirp);
功能
关闭目录。
示例
#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <dirent.h>int get_file_count(char * root){ DIR * dir = NULL; dir = opendir(root); if(dir == NULL) { perror("opendir"); exit(1); } struct dirent * ptr = NULL; char path[1024] = {0}; int total = 0; while(ptr = readdir(dir) != NULL) { //过滤.和.. if(strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) { continue; } //如果是目录 if(ptr->d_type == DT_DIR) { sprintf(path, "%s/%s", root, ptr->d_name); total += getFileNum(path); } //如果是文件 if(ptr->d_type == DT_REG) { total++; } } closedir(dir); return total;}int main(int argc, char * argv[]){ if(argc < 2) { printf("./a.out dir\n"); exit(1); } int total = get_file_count(argv[1]); printf("%s has file numbers %d\n", argv[1], total); return 0;}
6、fcntl函数
函数定义
int fcntl(int fd, int cmd, ... /* arg */ );
功能
改变已经打开的文件的属性。1、复制一个现有的描述符 -- cmd F_DUPFD2、获取/设置文件描述符标记 -- cmd F_GETFD F_SETFD3、获取/设置文件状态标记 -- cmd F_GETFL O_RDONLY 只读打开 O_WRONLY 只写打开 O_RDWR 读写打开 O_EXEC 执行打开 O_SEARCH 搜索打开目录 O_APPEND 追加写 O_NONBLOCK 非阻塞模式 F_SETFL, 可更改的几个标识 O_APPEND O_NONBLOCK4、获取/设置异步I/O所有权 -- cmd F_GETOWN F_SETOWN5、获取/设置记录锁 -- cmd F_GETLK F_SETLK F_SETLKW
示例
#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <unistd.h>#include <string.h>int main(int argc, char * argv[]){ int fd; int flag; //测试字符串 char * p = "we are family!"; cahr * q = "yes, man."; //只写的方式找开文件 fd = open("test.txt", O_WRONLY); if(fd == -1) { perror("open"); exit(1); } //输入新的内容,该部分会覆盖原来旧的内容 if(write(fd, p, strlen(p)) == -1) { perror("write"); exit(1); } //使用F_GETFL命令得到文件状态标志 flag = fcntl(fd, F_GETFL, 0); if(flag == -1) { perror("fcntl"); exit(1); } //将文件状态标志添加“追加写”选项 flag |= O_APPEND; //将文件状态修改为追加写 if(fcntl(fd, F_SETFL, flag) == -1) { perror("fcntl -- append write"); exit(1); } //再次输入新内容,该内容会追加到旧内容的后面 if(write(fd, q, strlen(q)) == -1) { perror("write again"); exit(1); } //关闭文件 close(fd); return 0;}
7、dup, dup2函数
函数定义
int dup(int oldfd);int dup2(int oldfd, int newfd);
功能
复制现有的文件描述符。
返回值
dup返回的是文件描述符中没有被占用的最小的文件描述符
注意事项
dup2两种情况:1、old --> new, 如果new是一个被打开的文件描述符,在拷贝前先关掉new。2、old和new是同一个文件描述符,不会关掉new,直接返回old。
dup示例
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>int main(){ int fd = open("a.txt", O_RDWR); if(fd == -1) { perror("open"); exit(1); } printf("file open fd = %d\n", fd); //找到进程文件描述表中==第一个==可用的文件描述符 //将参数指定的文件复制到该描述符后,返回这个描述符 int ret = dup(fd); if(ret == -1) { perror("dup"); exit(1); } printf("dup fd = %d\n", ret); char * buf = "你是猴子派来的救兵吗???\n"; char * buf1 = "你大爷的,我是程序猿!!!\n"; write(fd, buf, strlen(buf)); write(ret, buf1, strlen(buf1)); close(fd); return 0;}
dup2示例
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>int main(){ int fd = open("english.txt", O_RDWR); if(fd == -1) { perror("open"); exit(1); } int fd1 = open("a.txt", O_RDWR); if(fd1 == -1) { perror("open"); exit(1); } printf("file open fd = %d\n", fd); printf("file open fd1 = %d\n", fd1); //调用dup2后,fd1和fd同时指向了a.txt int ret = dup2(fd1, fd); if(ret == -1) { perror("dup2"); exit(1); } printf("current fd = %d\n", ret); char * buf = "主要看气质^_^!!!!!!!!!!!\n"; write(fd, buf, strlen(buf)); write(fd1, "hello, world!", 13); close(fd); close(fd1); return 0;}
解决gcc编译过程中c99语法报错的问题
alias gcc='gcc -std=gnu99'
索引节点inode:保存的其实是实际的数据的一些信息,这些信息称为“元数据”(也就是对文件属性的描述)。例如:文件大小,设备标识符,用户标识符,用户组标识符,文件模式,扩展属性,文件读取或修改的时间戳,链接数量,指向存储内容的磁盘区块的指针,文件分类等等。(注意数据分成:元数据+数据本身)
注意inode怎样生成的:每个inode节点的大小,一般是128字节或256字节。inode节点的总数,在格式化时就给定(现代OS可以动态变化),一般每2KB就设置一个inode。一般文件系统中很少有文件小于2KB的,所以预定按照2KB分,一般inode是用不完的。所以inode在文件系统安装的时候会有一个默认数量,后期会根据实际的需要发生变化。
注意inode号:inode号是唯一的,表示不同的文件。其实在Linux内部的时候,访问文件都是通过inode号来进行的,所谓文件名仅仅是给用户容易使用的。当我们打开一个文件的时候,首先,系统找到这个文件名对应的inode号;然后通过inode号,得到inode信息,最后,由inode找到文件数据所在的block,现在可以处理文件数据了。
inode与文件的关系:当创建一个文件的时候,就给文件分配了一个inode。一个inode只对应一个实际文件,一个文件也会只有一个inode。inode最大数量就是文件的最大数量。
强者能同命运的风暴抗争。