一、Linux基础介绍及环境搭建
1.linux操作系统的特点:基本思想:一切皆文件
特点:
完全免费
支持多平台
支持多任务、多用户
有良好的界面
2.什么叫做操作系统:管理计算机的软件和硬件的计算机程序。
3.为什么要有操作系统:单纯的裸机程序已经无法满足硬件的利用率。
常见的操作系统:
windows;MAC/IOS;安卓;鸿蒙;麒麟;
wince ucos freeos:小型的嵌入式系统;
openwrt:主要用于路由器
4.Ubuntu 版本及版本号
桌面版(desktop):侧重点在于图形界面,简单易用性。
服务器版(Server):侧重于性能,高效性,没有图形界面。
5.Linux的目录类型:
目录为树形结构;
根目录 用/表示;
.或者./表示当前目录;
..表示上一级目录;
绝对路径:从根目录开始;
相对路径:从当前路径开始;
6.shell指令
whs@WHS:~/002/0620/note$
@之前:用户名 @和:之间:主机名
~:家目录 普通用户:/home/用户名 超级用户: /root/
$:表示当前登录的用户为普通用户
#:表示当前登录的用户为管理员用户
查看帮助文档:man + 指令
man + 函数名 :查看函数的帮助文档
指令 + --help :查看指令的帮助文档
指令的格式
ls [OPTION]... [FILE]...
中括号中间的东西为可选项 可有可无
快捷操作:
*:匹配所有
?:匹配一个字符
tab:自动补全
- 用户管理类命令:
adduser:添加用户,并新增用户对应的家目录
deluser:删除用户
su root:从普通用户切换到超级用户
su 用户名:由超级用户切换到普通用户或(输入命令exit)
passwd:假如是普通用户,只能修改自己的账户的密码
假如是超级管理员用户,可以设置或修改任何用户的密码。
sudo :暂时借用管理员权限
- 文件目录类命令:
ls:查看某个目录下现在所有文件
ls -l:除文件名称外,亦将文件型态、权限、拥有者、文件大小等资讯详细列出;
ls -ail:a显示所有文件及目录,i打印文件索引节点,l如上,这算一个组合指令。
cd 切换目录
cd -: 切换到上次操作的目录
mkdir 创建目录
mkdir -p :1.创建多级目录
2.假如文件存在 则跳过 假如文件不存在 则创建
touch:创建一个空文件
rm:删除 rm -rf:强制删除 rm 目录名 -r:删除目录
cp:拷贝 mv:剪切
ln:链接
硬链接:ln 原文件 目标文件 //相当于文件的副本,别名
文件索引节点和原文件一样;
软连接 :ln -s 目标文件 链接名 //快捷方式(相当于文件的快捷方式)文件索引节点和原文件不一样;
程序的执行:./a.out
type:查看一个命令的执行路径
type gedit 的输出是 /usr/bin/gedit
tar:
压缩:tar cvf test.tar 1.c //把1.c文件压缩成test.tar压缩包
解压缩:
tar xvf test.tar -C 目的目录:解压到指定目录
eg:tar xvf 2.tar -C ../hw
查看历史命令:history |grep
- 系统相关的指令
ps :查看进程的状态
ps -aux 显示所有包含其他使用者的行程
ps -ef 显示所有命令,连带命令行
top:动态的查看系统的状态
- 网络管理相关的指令
ifconfig:查看网络信息
ifconfig ens33 192.168.168.168 //修改ens33(用户)的ip
ifconfig ens33 down/up //关闭或者打开网卡
/etc/init.d/networking restart //重启网络
ping www.baidu.com //查看网络通不通
- 其他的指令:
cat :不打开文件查看文件的内容
chmod:修改文件的权限
rw- rw- r--
110 110 100 对应2进制,有权限为1,无权限为0
6 6 4 对应八进制(3个2进制对应一个8进制)
rwx rwx rwx
111 111 111
7 7 7
chmod 777 test.c 把test.c所有权限打开
通过用户来修改文件的权限
u:所有者
g:同组用户
o:其他用户
a:所有用户
chmod a+x test.c //为所有的用户加上可执行权限
echo:回显
- 软件安装相关的指令
离线:
dpkg -i xxx.deb:离线安装软件
dpkg -r xxx.deb :离线卸载
dpkg -r -p:连同配置文件一起删除
在线:
apt-get install vim:在线安装
apt-get remove vim :在线卸载
apt-get update :更新软件源的列表
apt-get upgrade :更新软件
7.可传参函数
int main(int argc,char* argv[])
argc:传参的个数 包含自身
argv:传的参数
argv[0]:可执行程序本身
argv[1]:真正的第一个参数
二、Linux下常用工具
1.编辑器(vim)
在线安装:sudo apt-get install vim
打开文件:vim 文件名
若存在,打开;不存在,创建并打开
设置vim编辑器:
1)把tab键默认8空格改为4空格,用vim打开文件/etc/vim/vimrc,在文件最后加入:set ts=4;注意:vimrc文件是否是可写文件,需要用chmod:修改文件的权限,修改为666,这里当自己修改第三组为rw-才可以进行修改,或者用sudo vim /etc/vim/vimr直接进行修改
rw- rw- rx-
110 110 110
6 6 6
2)显示行号 在vimrc文件最后加入 set nu
工作模式:四种
命令模式:打开后默认进入
文本的删除:
d0:删除光标所在的位置到行首的字符
D或者d$:删除光标到行尾
(n)dd:删除光标所在的行//3dd删除光标所在行往下三行
文本的复制:
(n)yy:复制光标所在的行 //3yy复制光标所在行往下三行
p:将复制的内容粘贴到光标所在行的下一行
u:撤销操作
ctrl+r:反撤销
屏幕的滚动(n代表数字)
ctrl+d:向后滚动半屏
ctrl+u:向前滚动半屏
ctrl+f:向后滚动一屏
ctrl+b: 向前滚动一屏
n+enter:向下移动n行
0:光标跳到行首
$:光标跳到行尾
n+G:跳到某一行
gg:跳到文件的开始最开头的位置
G:跳到文件的最后一行开头
在命令行模式下输入:shift zz:保存并退出vim编辑器。
插入模式:按a、i、o(大小写均可)进入,ESC退出插入模式
a:插入到光标之后 A:插入光标所在行行尾
i:插入到光标所在位置 I:插入光标所在行行首
o:插入光标所在行下一行(新增的行)
O:插入光标所在行的上一行(新增的行)
底行模式:输入:(冒号)进入
q!:强制退出
w:保存
w!:强制保存
wq:保存并退出
wq!:强制保存并退出
字符串查找:/字符串 在键盘上按n:表示向下查找 按N:表示向上查找
?字符串 在键盘上按n:表示向下查找 按N:表示向上查找
字符串替换:
:%s/源串/目标串 :替换当前文件所有行的第一个源串为目标串
:%s/源串/目标串/g :替换文本中的所有的源串为目标串
视图模式:在命令行模式下,按v进入
d:删除
y:复制
x:剪切
p :粘贴到光标之后
2.编译器(gcc):把C语言代码转换成机器可以识别的二进制代码
预处理:处理伪指令(#)和特殊的符号
gcc -E main.c -o main.i
编译:把预处理完的文件生成相应的汇编语言
gcc -S main.i -o main.s
汇编:将汇编语言转换成2进制文件
gcc -c main.s -o main.o
或 as main.s -o main.o //as汇编编译器
链接库:找到指定路径下的库文件
gcc main.o -o main
gcc的选项
gcc main.c 不加任何选项,会在.c文件的同目录下产生一个可执行程序a.out
-o:指定输出的文件名
-c:只编译不链接
-g:产生GDB的调试信息,这个主要用来调试代码。
3.动态库和静态库
库:包含了通用函数的数据和二进制可执行机器码的文件。
分类:静态库(xxx.a)和动态库(xxx.so)
静态库创建:
1)准备功能文件 main.c func1.c func2.c func3.c
2)只编译不链接
gcc -c func1.c -o func1.o
gcc -c func2.c -o func2.o
gcc -c func3.c -o func3.o
3)打包生成静态库
ar rc libmyfunc.a func1.o func2.o func3.o
4)利用静态库编译程序
gcc main.c -o main -lmyfunc -L ./(当前目录)
-l:指定依赖的库
-L:指定库文件所在的位置
动态库的创建 第一种方法
1)准备功能文件 main.c func1.c func2.c func3.c
2)只编译不连接
gcc -fPIC -shared -c func1.c -o func1.o
gcc -fPIC -shared -c func2.c -o func2.o
gcc -fPIC -shared -c func3.c -o func3.o
3)打包生成动态库
gcc -fPIC -shared func1.o func1.o func1.o -o libmyfunc.so
4)利用动态库编译程序
gcc main.c -o main -lmyfunc -L ./
5)执行可执行程序 ./a.out
在执行的时候,它会去lib或者usr/lib里去找myfunc库,就需要自己手动将这个库放入lib或者usr/lib下
执行:sudo cp libmyfun.so /lib
动态库的创建 第二种方法
1)准备功能文件 main.c func1.c func2.c func3.c
2)只编译不连接
gcc -fPIC -shared -c func1.c -o func1.o
gcc -fPIC -shared -c func2.c -o func2.o
gcc -fPIC -shared -c func3.c -o func3.o
3)打包生成动态库
gcc -fPIC -shared func1.o func1.o func1.o -o libmyfunc.so
4)先将编译生成的动态库放到lib或者usr/lib下
执行:sudo mv libmyfun.so /lib
5)利用动态库编译程序
gcc main.c -o main -lmyfunc
6)直接执行程序
动态库的创建以及使用 第三种方法(目前了解)
1)准备功能文件 main.c func1.c func2.c func3.c
2)只编译不连接
gcc -fPIC -shared -c func1.c -o func1.o
gcc -fPIC -shared -c func2.c -o func2.o
gcc -fPIC -shared -c func3.c -o func3.o
3)打包生成动态库
gcc -fPIC -shared func1.o func1.o func1.o -o libmyfunc.so
4)编译程序:在编译的时候,它会去lib或者usr/lib里去找库
gcc main.c -o main -lmyfunc -L ./
5)修改环境变量
在/etc/profile里面加上一句话:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/duanweizheng/work/203/2/so/
6)执行程序 ./main
4.GDB:调试代码,发现代码的问题的
代码出现bug之后:
1)测试:发现代码中的bug
2)固化:让bug重现
3)确定出现bug的位置
4)修改
5)验证
要想使用gdb调试工具,必须要求我的可执行程序里有gdb的调试信息,在编译代码的时候加上-g gcc -g main.c -o main
启动gdb:gdb 可执行程序 eg:gdb ./a.out
gdb相关的指令:
l:list 列出源码信息
r:运行一个程序
b 行号:在某一行设置断点
info breakpoints:查看所有断点信息
cont:继续运行程序 直到下一个断点
d 断点号:删除断点
disable 断点号(不是行号):失能断点
enable 断点号:使能断点
clear 行号:清除某一行的断点
p 变量名:打印当前变量的值
start:启动按步调试
next:一步一步的执行程序,遇到函数调用会将这个函数执行完
step:一步一步的执行程序,遇到函数调用会进入到函数的内部一步 一步的执行
finish:进入函数里面后按步执行,输入finish退出这个函数这个时 候才有意义
quit:退出gdb的调试
where:假如代码出现段错误,可以定位段错误的位置
5.makefile:是一种脚本语言,实现编译代码的自动化
make指令: 他会默认的去找makefile
指定使用某一个makefile(mk) (自定义的makefile文件) make -f makefile(mk) make -f mk clean
makefile的组成
目标:依赖
由依赖生成目标的规则 (命令)
目标 依赖的文件可以是依赖多个文件
main:main.o
gcc main.o -o main
由依赖生成目标的规则,这一行必须按Tab键,不能自己空格
注释:用#,这一行就会被注释掉
特殊的宏
$@:可以替换目标文件
$^:替换所有的依赖的文件
$<:替换第一个依赖的文件
makefile的主目标和次目标
主目标:最上边的目标
次目标:跟主目标同级,并且没有依赖关系的目标
伪目标:
all:后边跟想要执行的目标
clean:跟删除的一些命令
声明伪目标
.PHONY:clean
三、文件操作
1.文件的概念:存储在外部介质上的数据的集合。
2.文件的分类
普通文件 -
目录文件 d
字符设备文件 c
块设备文件 b
管道文件 p
套接字文件 s
链接文件 l
3.标准的文件描述符
每个程序在执行的时候 会默认的打开三个文件描述符
0:标准输入 stdin
1:标准输出 stdout
2:标准错误 stderr
2 > &1:将标准错误,重定向到标准输出
>:表示重定向,假如重定向到文件里,会把文件里原有的内容清空
>>:表示重定向,假如重定向到文件里,会在文件的末尾追加内容
4.缓冲区的特点及作用
特点:读或者写的操作,先将内容写到缓冲区,当满足了一定的条件之后(遇到\n fflush return exit 缓冲区满等),再将缓冲区里面的内容写入到文件里。
作用:cpu的处理的速度很快,假如要操作数据,假如从硬盘里读会浪费cpu的资源,缓冲区的作用就是为了协调低速的输入设备和高速的cpu的
5.缓冲区的文件操作
1)文件的打开
fopen();
函数原型:FILE *fopen(const char *path,const char *mode);
头文件:STDIO.H
函数作用:以指定文件路径和一定的模式打开一个文件。
形参:
path:所打开的文件路径,如果是当前工作目录下的文件,可以不用加路径名,如果是其他目录下的则需要加路径。
mode:打开模式
返回值:打开成功,返回指向这个打开的文件流指针(文件描述符(FILE * ));\$不成功,返回NULL。
mode:模式
r :只读的方式打开文件,光标定位在文件开头
r+:读写的方式打开文件,光标定位在文件开头
w:清空写
如果文件存在,截取长度为0,如果文件不存在,创建文件,只写的方式打开,光标定位在文件开头
w+:(清空读写)读写的方式,如果文件存在,截取长度为0,如果文件不存在,创建文件,读写的方式打开,光标定位在文件开头。
a:追加写 - 光标在文件末尾
文件存在:追加写
文件不存在:创建文件
a+:读写
根据你第一次的操作,确定光标位置:
第一次是读:光标在文件开头
第一次是写:光标在文件末尾。
2)文件的关闭
fclose();
函数原型:int fclose (FILE *stream);
头文件:STDIO.H
函数作用:关闭已打开的文件流。
形参:
stream:文件流
返回值:关闭成功,返回0;\$如果出现任何错误,返回非零。
3)单字符读写
getchar():从键盘获取一个字符
函数原型:#define getchar() getc(stdin)
头文件:STDIO.H
函数作用:从标准输入流中读取一个字符。
形参:无
返回值:返回读取的字符。
putchar():输出字符到屏幕上
函数原型:#define putchar(c) putc((c), stdout)
头文件:STDIO.H
函数作用:向标准输出流中写入一个字符.
形参:
c:需要写入的字符
返回值:返回写入到标准输出流中的字符.
fputc():向文件中写入单个字符
函数原型:int fputc(int c, FILE *stream);
头文件:STDIO.H
函数作用:向文件流的当前位置写入一个字符。
形参:
c:字符的ASCII码
stream:文件流指针
返回值:返回写入的字符。
fgetc():从文件中读取单个字符
函数原型:int fgetc(FILE *stream);
头文件:STDIO.H
函数作用:从文件流(stream)读一个字符。
形参:
stream:文件流指针
返回值:返回正确读取的字符。
4)字符串读写
fputs:写入到文件中
函数原型:int fputs(const char *s, FILE *stream);
头文件:STDIO.H
函数作用:向文件流的当前位置写入一字符串。
形参:
s:需要写入的字符串
stream:文件流指针
返回值:返回最后一个被输出到文件流中的字符;\$如果没有数据输出到文件流,则返回0。
fgets:从文件中读取
函数原型:char *fgets (char *s, int n, FILE *stream);
头文件:STDIO.H
函数作用:从文件流中读取一个字符串。
形参:
s:存储读取的字符串的空间
n:读取字符的个数(个数中包含一个结束符('\0')),也就真正从文件流中读取的字符的个数就是n-1个。
stream:文件流指针
返回值:成功,返回读取的字符串。\$不成功,返回NULL。
5)按块读写
fread():从文件中读取数据
函数原型:size_t fread(void *ptr, size_t size, size_t n, FILE *stream);
头文件:STDIO.H
函数作用:fread 从文件流 stream 中读取 nmemb 个元素,写到 ptr 指向的内存中,每个元素的大小为 size 个字节。。
形参:
ptr:读取的数据的存储空间地址
size:每个元素的大小
n:读取的元素的个数(读取的次数)
stream:文件流指针(文件描述符(FILE * ))
返回值:返回读取的数据块的元素的个数。
fwrite():向文件中写入数据
函数原型:size_t fwrite(const void *ptr, size_t size, size_t n,FILE *stream);
头文件:STDIO.H
函数作用: fwrite 从 ptr 指向的内存中读取 nmemb 个元素,写到文件流 stream 中,每个元素 size 个字节。
参数:
ptr:需要写入到文件流中的数据块
size:数据块的组成元素的大小
n:数据块的元素个数(写入的次数)
stream:文件流指针(文件描述符(FILE * ))
返回值:返回写入的数据块的元素的个数。
6)格式化读写
fprintf():格式化的写入到文件
函数原型:int fprintf(FILE *stream, const char *format, ...);
头文件:STDIO.H
函数作用:向文件流写入格式化信息 。
形参:
stream:文件流
format:格式化字符串
... :可变参数,指明需要格式的数据
返回值:返回已经写入的字符数,出现错误返回EOF。
fscanf():格式化从文件中读取
函数原型:int fscanf(FILE *stream, const char *format, ...);
头文件:STDIO.H
函数作用:从文件流中格式化获取数据。
形参:
stream:文件流指针
format:格式化字符串
... :可变参数,指明需要格式的数据
返回值:返回可变参数中的正确获取数据的参数个数。
7)文件偏移操作
rewind():光标偏移到开头
函数原型:void rewind (FILE *stream);
头文件:STDIO.H
函数作用:将文件指针移动至文件开头位置。
形参:stream:文件流指针
返回值:无
fseek():
函数原型:int fseek (FILE *stream, long offset, int whence);
头文件:STDIO.H
函数作用:将文件指针指向whence所指位置的向后offset个字节处。
形参:
stream:文件流指针
whence:指定的位置
文件头 0(SEEK_SET),
当前位置 1(SEEK_CUR),
文件尾 2(SEEK_END))为基准
offset:与whence的偏移量
+往文件末尾方向偏移
-往文件开头方向偏移
返回值:成功,返回0;\$不成功,返回-1。
ftell():返回指针的位置,可以计算文件开头到光标处的偏移量
函数原型:long ftell(FILE *stream);
头文件:STDIO.H
函数作用:获得文件指针在文件流中的位置。
形参:stream:文件流指针
返回值:返回从文件的开头到文件指针所在的位置之间间隔的字节数。
8)输出错误
perror():输出错误的信息
函数原型:void perror(const char *s);
头文件:STDIO.H
函数作用:打印一条标准错误流中的一条错误信息:错误信息的标题由s指定,然后打印冒号,接着打印当前errno数值相对应的错误消息,最后打印换行符。
形参:
s:错误标题
返回值:无
9)其他
feof():判断是否到达文件末尾
函数原型:int feof(FILE *stream);
形参:stream文件描述符
返回值:到达文件末尾返回非0,没有到达文件末尾返回0;
注意:feof在判断是否到达文件末尾,用的是前一次读到的结果来判断。
6.非缓冲区的文件操作
1)文件的打开
open():打开一个文件
函数原型:
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
头文件:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
形参:
const char *pathname:打开文件
int flags:打开的方式
O_RDONLY:只读
O_WRONLY:只写
O_RDWR:读写
O_CREAT:假如文件不存在则新建
O_APPEND:追加
O_TRUNC:假如文件已经存在,且是一个普通文件,打开模式又是可写(即文件是用 O_RDWR 或 O_WRONLY 模式打开的) , 就把文件内容清零。
假如要以只写的方式打开文件,并且假如文件不存在则新建
open(“./1.tex”,O_WRONLY|O_CREAT,0664);
mode_t mode:权限 一般是配合O_CREAT使用的,他实际得到的权限是减去掩码的值(八进制数:0777)
查看掩码:umask
修改掩码的值 umask 0000
返回值:成功返回文件的描述符(一个int型整数)
失败返回 -1
2)文件关闭
close():
函数原型:int close(int fd);
头文件:#include <unistd.h>
函数作用:关闭文件。
形参:
fd:文件的描述符
返回值:成功返回 0
失败返回 -1
3)文件的读
read();
函数原型:ssize_t read(int fd, void *buf, size_t count);
头文件:#include <unistd.h>
函数作用:从打开的文件里读取内容
形参:
int fd:打开的文件的描述符
void *buf:读取到的内容存放的位置
size_t count:要读取的字节数
返回值:成功返回读到的字节数
失败 返回 -1
4)文件的写
write();
函数原型:ssize_t write(int fd, const void *buf, size_t count)
头文件:#include <unistd.h>
函数作用:向一个已打开的文件写入内容
形参:
int fd:打开的文件的描述符
const void *buf:要写入的内容
size_t count:要写入的字节数
返回值:成功返回 成功写入的字节数
失败返回 -1
5)指针定位
lseek();
函数原型:off_t lseek(int fd, off_t offset, int whence);
头文件:#include <unistd.h> #include <sys/types.h>
函数作用:重新定位文件的读写指针的位置
形参:
int fd:打开的文件的描述符
off_t offset:偏移量 可正可负
int whence:参考位置
SEEK_SET :文件的开头
SEEK_CUR:当前的位置
SEEK_END:文件的末尾
返回值:
成功返回指针距离文件头的距离
失败返回 -1
四、时间编程和目录操作
时间编程:
1.时间的表示方法
UTC:格林威治时间,世界标准时间,和北京时间错了8小时。
日历时间:从1970年1月1日0点到现在所经历秒数
本地时间:本计算机的时间 北京时间
2.与时间相关的shell命令
date //显示当前日期-- 中国北京时间
date –u //显示当前日期时间 -- 世界标准时间 UTC
date –R //显示当前日期时间 – RFC格式
cal:查看日历
3.获取日历时间
time():获取日历时间
函数的头文件:time.h
函数原型:time_t time(time_t *tloc);
函数的参数:time_t *tloc:获取到的日历时间的指针
函数的返回值:返回获取到的日历时间,返回值输出格式控制符%ld
4.转换格林威治时间
gmtime();
函数的头文件:time.h
函数原型:struct tm *gmtime(const time_t *timep);
函数的参数:const time_t *timep:日历时间
函数的返回值:
格林威治时间对应的结构体,struct tm *
5.获取本地时间
localtime():将日历时间转换成本地时间
函数的头文件:time.h
函数原型: struct tm *localtime(const time_t *timep);
函数的参数:const time_t *timep:日历时间
函数的返回值:
struct tm * 结构体的指针
struct tm {
int tm_sec; 秒
int tm_min; 分
int tm_hour; 小时
int tm_mday; 月中的天
int tm_mon; 月-1
int tm_year; 年-1900
int tm_wday; 星期 星期日 0
int tm_yday; 一年中的第几天
int tm_isdst; 夏令时
};
6.日历时间转换成本地时间
ctime():将日历时间转换成本地时间串
函数的头文件:time.h
函数原型: char *ctime(const time_t *timep)
函数的参数:const time_t *timep:日历时间
函数的返回值:用字符串表示的本地时间
文件属性的获取
1.stat();
函数功能:通过文件名来获取文件的属性
函数的头文件:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
函数原型: int stat(const char *pathname, struct stat *buf);
函数的参数:
const char *pathname:文件名
struct stat *buf:存放文件属性的
函数的返回值:成功返回 0,失败返回 -1
struct stat {
dev_t st_dev; 如果是设备,他就是设备表述符,否则就是0
ino_t st_ino; 节点号
mode_t st_mode; 文件类型以及权限
nlink_t st_nlink; 链接数
uid_t st_uid; 用户id
gid_t st_gid; 组id
dev_t st_rdev; 设备的类型
off_t st_size; 文件的大小
blksize_t st_blksize; 操作块的大小
blkcnt_t st_blocks; 块的索引
};
2.fstat();
函数功能:通过文件描述符,来获取文件的属性。
函数的头文件:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
函数原型: int fstat(int fd, struct stat *buf);
函数的参数:
int fd:打开文件获取到的文件描述符
struct stat *buf:存放文件属性的结构体的指针
函数的返回值:成功返回 0,失败返回 -1
3.lstat();
函数功能:获取文件属性,不需要打开文件。
函数的头文件:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
函数原型: int lstat(const char *pathname, struct stat *buf);
函数的参数:
const char *pathname:文件名
struct stat *buf:存放文件属性的结构体的指针。
函数的返回值:成功返回 0,失败返回 -1
4.三种获取文件属性的接口的区别
fstat:在获取文件属性的时候,要先打开文件,stat和lstat则不用打开文件
stat:假如获取的是链接文件属性,得到是链接文件指向的文件的属性
lstat:假如获取的是链接文件的属性,得到的是链接文件本身的属性
5.access();
函数功能:判断当前用户对某个文件是否有某个权限
函数的头文件:#include <unistd.h>
函数原型: int access(const char *pathname, int mode);
函数的参数:
const char *pathname:文件名
int mode:要测试的权限
R_OK 可读
W_OK 可写
X_OK 可执行
F_OK 文件是否存在
假如权限有很多种,R_OK | W_OK
函数的返回值:假如要查询的权限都有的话,返回 0,否则返回 -1
目录操作
1.创建目录:mkdir
函数功能:创建一个目录
函数的头文件:
#include <sys/stat.h>
#include <sys/types.h>
函数的原型:int mkdir(const char *pathname, mode_t mode);
函数的参数:
const char *pathname:目录文件名
mode_t mode :权限
函数的返回值:成功返回 0 失败返回 -1
2.删除目录:rmdir
函数功能:删除目录
函数的头文件:#include <unistd.h>
函数的原型:int rmdir(const char *pathname);
函数的参数:const char *pathname:要删除的目录文件的名字
函数的返回值:成功返回 0 失败返回 -1
3.获取当前目录:pwd
函数的功能:获取当前所在的路径
函数的头文件:#include <unistd.h>
函数的原型:
char *getcwd(char *buf, size_t size);
char *get_current_dir_name(void); //需在第一行加上 #define _GNU_SOURCE
函数的参数:
char *buf:保存当前路径
size_t size:最大为255
函数的返回值:目录的串的指针
4.更改文件权限:chmod
函数的功能:更改目录的权限
函数的头文件:#include <sys/stat.h>
函数的原型:int chmod(const char *pathname, mode_t mode);
函数的参数:
const char *pathname, :目录文件的名字
mode_t mode:权限
函数的返回值:成功返回 0 失败返回 -1
5.切换目录:cd
函数的功能:切换目录
函数的头文件:#include <unistd.h>
函数的原型:int chdir(const char *path);
函数的参数:const char *path:要切换到的目录
函数的返回值:成功返回 0 失败返回 -1
6.打开目录
函数的功能:打开一个目录
函数的头文件:
#include <sys/types.h>
#include <dirent.h>
函数的原型: DIR *opendir(const char *name);
函数的参数:const char *name:要打开的目录的名字
函数的返回值:成功返回目录流的指针 失败,返回 NULL.
7.关闭目录
函数的功能:关闭目录
函数的头文件:
#include <sys/types.h>
#include <dirent.h>
函数的原型:int closedir(DIR *dirp);
函数的参数:DIR *dirp:目录流指针
函数的返回值:成功返回 0 失败返回 -1
8.读取目录
函数的功能:读取目录里的信息
函数的头文件:#include <dirent.h>
函数的原型:struct dirent *readdir(DIR *dirp);
函数的参数:DIR *dirp:目录流指针
函数的返回值:
成功返回读取到文件的信息的结构体的指针
失败返回 NULL
存储目录中的文件信息(文件名、扩展名等等)
#include <dirent.h>
struct dirent
{
long d_ino; /* inode number 索引节点号 */
off_t d_off; /*在目录文件中偏移到到目录头的偏移量*/
unsigned short d_reclen; /* 文件名长 */
unsigned char d_type; /* 文件类型 */
char d_name [NAME_MAX+1]; /*文件名,最长255字符 */
};
9.目录读写指针偏移
函数的功能:将目录流的读写指针重新定位到目录流的头
函数的头文件:
#include <sys/types.h>
#include <dirent.h>
函数的原型:void rewinddir(DIR *dirp);
函数的参数:DIR *dirp:目录流指针
函数的返回值:无
10.获得目录读写指针偏移量
函数的功能:获取目录读写指针的偏移的位置
函数的头文件:#include <dirent.h>
函数的原型:long telldir(DIR *dirp);
函数的参数:DIR *dirp:目录流指针
函数的返回值:
成功返回距离目录流的头的偏移量
失败返回 -1
11.重新定位目录流读写指针
函数的功能:重新定位目录流的读写指针
函数的头文件:#include <dirent.h>
函数的原型:void seekdir(DIR *dirp, long loc);
函数的参数:
DIR *dirp:目录流指针
long loc:偏移量(到距离目录流的头的偏移量)
函数的返回值:无
五、进程初步
1.相关的概念
程序:可执行的二进制的代码
进程:程序被加载到内存中运行 ---进程
进程和程序的关系:一个程序可以被多次加载生成不同的进程
进程的查看:
linux下查看指令:ps -ef
uid:用户的id
PID:进程号
ppid:父进程号
c:cpu的占用率
ps -aux
stat显示的是进程的状态
S:睡眠
r:运行
d:不可中断的睡眠
T:停止
N:低优先级任务
Z:僵尸进程
X:死进程
+:跟用户交互
2.进程号:
唯一识别进程的东西
无符号的整形数32位
3.进程的状态
执行态:当前程序正在运行,进程正在占用cpu,任何时候都只有一个进程占用cpu.
就绪态:只要拿到了cpu就能运行的进程
等待态:除了没有拿到cpu之外 还缺少一些其他的资源
4.父进程和子进程的概念
父进程:创建一个进程的进程,该进程称为被创建的进程的父进程
子进程:相对于创建本进程的父进程来说,该进程即为创建本进程的进程的子进程.
子父进程的概念是相对的。
5.特殊的进程
0号进程:操作系统的引导程序
祖先进程:操作系统启动的第一个程序,1号进程
孤儿进程:父进程先退出,子进程被init进程托管,孤儿进程当进程退出的时候相关的资源,没有办法被清理回收。
僵尸进程:子进程退出的时候,父进程没有清理工作
6.内存的布局
每个进程在执行的时候,系统都会默认的给进程,虚拟出一块4G大小的内存空间。
0-3G:用户空间 系统阶段写的代码在这
3-4G:内核空间 驱动阶段写的代码放这
7.进程的特点
动态性:进程的实质是程序在多道程序系统中的一次执行过程,进程是动态产生,动态消亡的。
并发性:任何进程都可以同其他进程一起并发执行.
独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位;
异步性:由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推进。
8.进程的调度:按照一定的调度算法调用,这个我们无法干预。
9.常见的进程相关的函数
getpid(void):获取进程号
函数的头文件:
#include <sys/types.h>
#include <unistd.h>
函数的原型:pid_t getpid(void);
函数的参数:无
函数的返回值:成功返回当前进程的进程号%d
getppid(void):获取父进程号
函数的头文件:
#include <sys/types.h>
#include <unistd.h>
函数的原型:pid_t getppid(void);
函数的参数:无
函数的返回值:成功返回当前进程的父进程的进程号
fork():创建一个新的进程(重要)
函数头文件:#include <unistd.h>
函数的原型:pid_t fork(void);
函数的参数:无
函数的返回值:
在父进程里返回子进程的进程id
在子进程里返回 0
失败返回 -1
fork创建子进程的特点:
子进程会拷贝一份父进程的所有的资源 (包括三条语句)
子进程会从fork函数往下执行
父子进程有各自独立的数据段代码段,相互不干扰
无法确定父子进程的运行的顺序
注意:代码中,在fork上边的代码段只有父进程执行,在fork之下的,不单独在在父进程或者子进程的部分,两个进程都会调用。
vfork():创建子进程,并且阻塞父进程
函数的头文件
#include <sys/types.h>
#include <unistd.h>
函数的原型:pid_t vfork(void);
函数的参数:无
函数的返回值:
在父进程里返回子进程的进程id
在子进程里返回 0
失败返回 -1
函数的特点:
vfork成功之后会创建一个进程
子父进程共用(独占)资源,子进程退出执行之后,父进程才能执行。
子进程先执行,子进程在退出的时候一定要调用execl函数 或者exit函数。
10.进程相关函数(续)
1)进程等待函数:(目前只能通过在父进程中使用这类函数等待子进程结束的方式来避免产生孤儿进程)
wait():等待子进程结束
函数原型:pid_t wait(int *status);
头文件:sys/types.h sys/wait.h
参数:int *status:进程退出的状态,一般填NULL
返回值:成功返回终止的那个子进程的id,失败返回-1
waitpid():暂时停止目前进程的执行,直到有信号来到或子进程结束
函数原型:pid_t waitpid(pid_t pid, int *stat_loc, int options);
头文件:sys/types.h sys/wait.h
参数:
pid:
>0 等待指定的子进程结束
-1 等待任意的子进程结束
int *stat_loc, :一般填NULL
options:阻塞父进程,等待子进程退出--一般为0
返回值:成功返回子进程识别码(PID) ,失败返回-1
2)进程退出函数
exit():正常结束一个进程的执行
exit(0);表示正常退出,其他的值表示异常,在退出进程的时候会刷新缓冲区
_exit():正常的结束一个进程的执行
0表示正常,其他的值表示异常
将缓冲区的内容丢弃,不刷新缓冲区
return:结束进程
他的内部是调用的exit来实现的
信号:
ctrl +C:强制中断程序的执行,进程已经终止
ctrl + \:退出
ctrl + z:是将任务中止(暂停的意思),但是此任务并没有结束,相当于挂起状态
kill -9 进程号 跟进程发送9号信号,杀死进程
3)退出清理函数
atexit():注册退出清理函数,在任意进程结束的时候,自动执行退出清理函数(钩子函数)(在vfork中会报错)(在我虚拟机上是这样,可以自行测试)
原型:int atexit(void (*function)(void));
头文件:#include <stdlib.h>
参数:void (*function)(void) 函数指针,指向一个无参数,无返回值的函数。
返回值:成功返回0,失败返回非0
注意:该函数不需要被调用,只要在函数开始之前进行注册,在进程结束的时候就会自己执行。
4)执行程序函数
exec函数族:就是在一个进程中启动另外一个进程。
execl():让进程重生(放到父进程中,父进程重生,子程序正常运行,同理放到子程序中也不影响父进程的执行)
函数头文件: #include <unistd.h>
函数原型:int execl(const char *path, const char *arg, ...);
参数:
const char *path:你要执行的可执行程序的完整的名字加上路径
const char *arg:可执行程序的名
.....:可选的参数
返回值:成功 无 失败 返回-1
特点:当进程调用execl函数的时候,程序的代码段会被execl所要执行的功能代码段替换掉,参数要以NULL结尾
和fork的区别:fork产生一个新的子进程,有对应的pid,execl指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段
execlp():通过可执行程序让进程重生
函数头文件: #include <unistd.h>
函数原型:int execlp(const char *file, const char *arg, ...);
参数:
const char *file, :可执行程序的名字,他会去PATH环境变量指定的目录里去找(需要手动把要重生的可执行程序放到/bin目录(这是PATH中其中的一个目录)下面)。
const char *arg,:可执行程序的名字
...:可选参数
返回值:成功 无 失败 返回-1
shell指令的调用
函数功能:调用shell指令
头文件:#include <stdlib.h>
原型:int system(const char *command);
参数:const char *command:要执行的shell指定