目录
43、void *mmap(void *addr, size_t length, int prot, int fd, off_t offset);
44、 int munmap(void *addr, size_t length)
一、cmd命令
1.shell:
命令解释器,根据输入的命令执行相应命令。
察看当前系统下有哪些shell:
cat /etc/shells
察看当前系统正在使用的shell
echo $SHELL
1、常见shell:
/bin/sh (已经被 /bin/bash 所取代)/bin/bash (就是 Linux 默认的 shell)/bin/ksh (Kornshell 由 AT&T Bell lab. 发展出来的,兼容于 bash)/bin/tcsh (整合 C Shell ,提供更多的功能)/bin/csh (已经被 /bin/tcsh 所取代)/bin/zsh (基于 ksh 发展出来的,功能更强大的 shell)
2、主键盘快捷键
| 功能 | 快捷键 | 助记 ||-----------+-----------+------------------|| 上 | Ctrl-p | previous || 下 | Ctrl-n | next || 左 | Ctrl-b | backward || 右 | Ctrl-f | forward || Del | Ctrl-d | delete光标后面的 || Home | Ctrl-a | the first letter || End | Ctrl-e | end || Backspace | Backspace | delete光标前面的 |
2、目录和文件
linux系统: “所见皆文件”
linux系统目录:
bin:存放二进制可执行文件
boot:存放开机启动程序
dev:存放设备文件:字符设备、块设备
home:存放普通用户
etc:用户信息和系统配置文件 passwd、group
lib:库文件:libc.so.6
root:管理员宿主目录(家目录)
user:用户资源管理目录
Linux系统文件类型:7/8种
普通文件:-
目录文件:d
字符设备文件:c
块设备文件:b
软连接:l
管道文件:p
套接字:s
未知文件
ls:ls是英文单词list的简写,其功能为列出目录的内容
-a 列出隐藏文件,文件中以“.”开头的均为隐藏文件,如:~/.bashrc
-l 列出文件的详细信息-R 连同子目录中的内容一起列出
cd:change dir 改变当前所在路径
cd ~cd dir1/dir2cd ..
which:查看指定命令所在路径
which ls
pwd:查看当前所在路径
pwd
mkdir:
mkdir [OPTION] DIRECTORY…
rmdir:
$ mkdir a$ mkdir a/b$ ls ab$ rmdir a/b$ ls a$ rmdir a$ mkdir a/bmkdir: cannot create directory `a/b': No such file or directory$ mkdir -p a/b$ rmdir -p a/b
touth:
touch [OPTION]… FILE…
rm:
删除文件:rm file删除目录:rm dir -rf
mv
重命名:mv file1 file2移动文件:mv file1 ~/
cp
cp file1 file2cp file1 dir/cp file1 ../
cp dir1 dir2 -rcp dir1 ~/ -r
cat:
more:
more [OPTION] FILE…
查看文本文件的内容,屏幕显示完一屏就等待用户按下任意键再滚动到下一屏,如果中
less:
less [OPTION] FILE…
查看文本文件的内容,屏幕显示完一屏就等待用户按键,用户可以向上或向下查看,如
head:
head [OPTION]… FILE…
$ head -5 file1
tail:
tail [OPTION]… FILE…
$ tail -5 file1
3、文件属性和用户用户组
whoami:查看当前登录用户
软连接:
为保证软连接可以任意搬移,创建时务必对源文件使用绝对路径
硬连接:
ln file file.hard
操作系统给每一个文件赋予唯一的inode,当相同的inode文件存在时,彼此同步。
删除时,只将硬连接计数减一。减为0时,inode被释放。
创建用户:
sodo adduser 新用户名 ---useradd
修改文件所属用户:
sudo chown 新用户名 待修改文件
sudo chown wangwu a.c
删除用户:
sudo deluser 用户名
创建用户组:
sudo addgroup 新组名
修改文件所属用户组:
sudo chgrp 新用户组名 待修改文件
sudo chgrp g88 a.c
删除组:
sudo delgroup 用户组名
使用chown一次修改所有者和所属组:
sudo chown 所有者:所属组 待操作文件
4、查找与检索
find命令:找文件
-type 按文件类型搜索 d/p/s/c/l/f:文件
-name 按文件名进行搜索 find ./ -name "*file*.jpg"
-maxdepth 指定搜索深度。应作为第一个参数出现 find ./ -maxdepth 1 -name "*file*.jpg"
-size 按文件大小搜索,单位:k、M、G find /home/itcast -size +20M -50M
-atime、mtime、ctime 天 amin、amin、cmin 分钟
-exec: 将find搜索的结果即执行某一指令。 find /user/ -name '*tem*' -exec ls -ld {} \;
-ok:以交互式的方式,将find搜索的结果集执行某一指定命令
-xargs:将find搜索的结果集执行某一指定命令。 当结果集数量较大时,可以分片映射。
find /user/ -name '*tmp' | xargs ls -ld
-print0: find /user/ -name '*tmp*' | -print0 | xargs -0 ls -ld
grep命令:找文件内容
grep -r 'copy' ./ -n -n:参数:显示行号
ps aux | grep 'cupsd' --检索进程结果集
软件安装:
1、联网
2、更新软件资源列表到本地:sudo apt-get update
3、安装 sudo apt-get install 软件名
4、卸载 sudo apt-get remove 软件名
5、使用软件包(.deb)安装: sudo dpkg -i 安装包名。
tar压缩:
tar -zcvf 要生成的压缩包名 压缩材料
tar zcvf test.tar.gz file1 dir2 使用 gzip 方式压缩
tar jcvf test.tar.gz file1 dir2 使用 bzip2 方式压缩
tar解压:
将压缩命令中的c --> x
tar zxvf test.tar.gz 使用 gzip 方式压缩
tar jxvf test.tar.gz 使用 bzip2 方式压缩
rar压缩:
rar a -r 压缩包名 (带.rar后缀)压缩材料
rar a -r testrar.rar stdio.h test.mp3
rar解压
unrar x 压缩包名 (带.rar后缀)
zip压缩:
zip -r 压缩包名(带.zip后缀)压缩材料
zip -r testzip.zip stdio.h test.mp3
zip解压
unzip 压缩包名 (带.rar后缀)
5、vim编辑器
跳转到指定行:
1. 88G(命令模式)
2. 88 (末行模式)
跳转文件首:
gg (命令模式)
跳转文件尾:
G(命令模式)
自动格式化程序:
gg=G(命令模式)
大括号对应:
% (命令模式)
光标移至行首:
0 (命令模式)执行结束,工作模式不变
光标移至行尾:
$ (命令模式)执行结束,工作模式不变
删除单个字符:
x (命令模式)执行结束,工作模式不变
替换单个字符:
将待替换的单词用光标选中,r (命令模式),在按欲替换的字符
删除一个单词:
dw(命令模式) 光标置于单词的首字母进行操作
删除光标至行尾:
D或d$(命令模式)
删除光标至行首:
d0(命令模式)
删除指定区域:
按V(命令模式)切换为"可视模式",使用 hjkl挪移光标来选中待删除区域。按d删除该区域数据
删除指定一行:
在光标所在行,按dd(命令模式)
删除指定N行:
在光标所待删除首行,按Ndd(命令模式)
复制一行: yy
粘贴:p:向后 P:向前
查找:
1、找 设想内容:
命令模式下,按“/”输入欲搜索关键字,回车。使用n检索下一个
2、找 看到的内容
命令模式下,将光标置于单词任意一个字符上,按“ * ” / " # "
单行替换:
将光标置于待替换行上,进入末行模式,输入:s/原数据/新数据
通篇替换:
末行模式, :%s /原数据/新数据/g g不加,只替换每行首个
指定行的替换:
末行模式, :起始行号,终止行号s /原数据/新数据/g g不加,只替换每行首个
撤销、反撤销:
u、ctrl+r(命令模式)
分屏:
sp:横屏分。ctrl+ww切换
vsp:竖屏分。ctrl+ww切换
跳转至man手册
将光标置于待查看单词函数上,使用 K (命令模式) 跳转。指定卷, nK
查看宏定义:
将光标置于待查看的宏定义单词上,使用[d 查看定义语句
在末行模式执行shell命令
:!命令
6 、gcc编译:
4步骤: 预处理、编译、汇编、连接
-I: 指定头文件所在目录位置
-c: 只做预处理、编译、汇编。得到二进制文件
-g: 编译时添加调试语句。主要支持gdb调试
-Wall:显示所有警告信息
-l: 指定动态库名
-L: 指定动态库路径
-D: 向程序中“动态”注册宏定义。 #define NAME VALUE
7、静态库的制作及使用步骤:
1、将.c生成.o文件
gcc -c add.c -o add.o
2、使用 ar 工具制作静态库
ae rcs lib库名.a add.o sub.o div.o
3、编译静态库到可执行文件中
gcc test.c lib库名.a -o a.out
头文件守卫:防止头文件被重复包含
#ifndef _HEAD_H
#define _HEAD_H
.......
#endif
动态库制作及使用
1、将.c生成.o文件 (生成与位置无关的代码 -fPIC)
gcc -c add.c -o add.o -fPIC
2、使用gcc -shared制作动态库
gcc -shared lib库名.so add.o sub.o div.o
3、编译可执行程序时,指定所使用的动态库
-l:指定库名(去掉lib前缀和.so后缀)-L:制定库路径
gcc test.c -o a.out -lmymath -L ./lib
4、运行可以执行程序 ./a.out 出错!!! ---ldd a.out -->"not found"
error while loading shared libraries:libxxx.so: cannot open shared object file: No such file or directory
原因:
链接器: 工作于链接阶段,工作时需要-l 和-L
动态链接器:工作于程序运行阶段,工作时需要提供动态库所在目录位置
解决方式:
(1)通过环境变量: export LD_LIBRARY_PATH=动态库路径
./a.out 成功!!! (临时生效,终端重启环境变量失效)
(2)永久生效: 写入终端配置文件。 .bashrc 建议使用绝对路径
a. vi ~/.bashrc
b. 写入 export LD_LIBRARY_PAHT=动态库路径 保存
c. ..bashrc/ source .bashrc / 重启 终端 ---》让修改后的.bashrc生效
d. ./a.out 成功!
(3)拷贝自定义动态库 到/lib(标准C库所在目录位置)
(4)拷贝文件法
a. sudo vi /etc/ld.do.conf
b. 写入 动态库绝对路径 保存
c. sudo ldconfig -v 使配置文件生效
d. ./a.out 成功!!! --- 使用ldd a.out 查看
8、gdb调试工具
大前提:程序是自己写的
基础指令:
-g:使用该参数编译可执行文件,得到调试表
gdb a.out
list: l 1 列出源码。根据源码指定 行号设置断点
b: b 20 在20行位置设置断点
run/r: 运行程序
n/next:下一条指令(会越过函数)
s/step: 下一条指令(会进入函数)
p/print: p i 查看变量的值
continue:继续执行断点后续指令
quit: 退出当前调试
其他指令:
run:使用run查找段错误出现位置
finish:结束之前函数调用
set args:设置main函数命令行函数
run:字符串1 字符串2 ...: 设置main函数命令行参数
info b: 查看断点信息表
b 20 if i = 5 : 设置条件断点
ptype:查看变量类型
bt:列出当前程序正存活着的栈帧
frame:根据栈帧编号,切换栈帧
display:设置跟踪变量
undisplay:取消设置跟踪变量,使用跟踪变量的编号
9、Makefile项目管理
1个规则:
目标:依赖条件
(一个tab缩进)命令
1、目标的时间应该晚于依赖条件的时间,否则,更新目标
2、依赖条件如果不存在,找寻新的规则去产生依赖
2个函数:
src = $(wildcard ./*.c):匹配当前工作目录下所有.c文件。将文件名组成列表,赋值给变量src
obj = $(patsubst %. c, %. o, $(src)):将参数3中,包含参数1的部分,替换为参数2
clean:(没有依赖)
-rm -rf $(obj) a.out "-":作用是,删除不存在文件时不报错。顺序执行结束。
3个自动变量:
$@:在规则的命令中,表示目标。
$^:在规则的命令中,表示所有依赖条件
$<:在规则的命令中,表示第一个依赖条件。如果将该变量应用在模式规则中,它可将依赖条件列表中的依赖取出,套用模式规则。
模式规则:
%.o:%.c
gcc -c $< -o %@
静态模式规则:
$(obj): %. o:% .c
fcc -c $< -o %@
伪目标:
.PHONY: clean ALL
参数:
-n: 模拟执行 make、make clean文件
-f:指定文件执行make命令 xxxx.mk
10、open函数
int open(char *pathname, int flags) #include <unistd.h>
参数:
pathname:欲打开的文件路径名
flags:文件打开方式: #include <fcntl.h>
O_RDONLY|O_WRONLY|O_RDWR
O_CREAT|O_APPEND|O_TRUNC|O_EXCL|O_NONBLOCK
返回值:
成功:打开文件所对应的文件描述符(整数)
失败:-1,设置error
int open(char *pathname,int flags,mode_t mode)
参数:
pathname:欲打开的文件路径名
flags:文件打开方式: #include <fcntl.h>
O_RDONLY|O_WRONLY|O_RDWR
O_CREAT|O_APPEND|O_TRUNC|O_EXCL|O_NONBLOCK
mode:参数3使用的前提,参2指定了O_CREAT。
取值8进制数,用来描述文件的访问权限
创建文件最终权限=mode & ~mask
返回值:
成功:打开文件所对应的文件描述符(整数)
失败:-1,设置error
11、close函数
int close(int fd);
12、错误处理函数: 与errno相关
1、 printf("xxx errno: %d\n", errno);
2、char *strerror(int errnum);
printf("xxx error: %s\n", strerror(errno));
3.void perror (const char *s)
perror("open error");
13、read函数
ssize_t read(int fd, void *buf,size_t count );
参数:
fd:文件描述符
buf:存数据的缓冲区
count:缓冲区大小
返回值:
0:读到文件末尾
成功:读到的字节数
失败:-1,设置errno
-1:bingqie errno=EAGIN 或 EWOULDBLOCK,说明不是read失败,而是read再以非阻塞方式读一个设备文件(网络文件),并且文件无数据。
14、write函数
ssize_t write(int fd, const void *buf,size_t count );
参数:
fd:文件描述符
buf:待写出数据的缓冲区
count:数据大小
返回值:
成功:写入的字节数
失败:-1,设置errno
15、文件描述符:
PCB进程控制块:本质 结构体
成员:文件描述符表
文件描述符:0/1/2/3/4......./1023 表中可用的最小的
0 - STDIN_FILENO
1 -STDOUT_FILENO
2 - STDERR_FILENO
16、阻塞、非阻塞
产生阻塞事件的场景:读设备文件。读网络文件。(读常规文件无阻塞概念)
/dev/tty --终端文件
open("/dev/tty", O_RDWR|O_NOBLOCK) -------设置/dev/tty 非阻塞状态(默认为阻塞状态)
17、fcntl:
int flags= fcntl(fd,F_GETFL);
flags |= O_NOBLOCK
fcntl(fd, F_SETFL,flags)
获取文件状态:F_GETFL
设置文件状态:F_SETFL
18、lseek函数
off_t lseek(int fd, off_t offset, int whence);
参数:
fd:文件描述符
offset:偏移量
whence:起始偏移位置:SEEK_SET/SEEK_CUR/SEEK_END
返回值:
成功:较起始位置偏离量
失败:-1 errno
应用场景:
1、文件的“读”、“写”使用使用同一偏移位置
2、使用lseek获取、拓展文件大小
使用truncate函数,直接拓展文件。 int ret=truncate(“dict.cp”,250)
19、 传入参数:
1、指针作为函数参数。
2、通常有const关键字修饰。
3、指针指向有效参数,在函数内部做读操作
20、传出参数
1、指针作为函数参数
2、 在函数调用之前,指针指向的空间可以无意义,但必须有效
3、在函数内部,做写操作
4、函数调用结束后,充当函数返回值
21、传入传出参数
1、指针作为函数参数
2、在函数调用之前,指针指向的空间有实际意义
3、函数调用结束之后,充当函数返回值
22、start/latat函数
int stat(const char *path,struct stat *buf)
参数:
path:文件路径
buf:(传出参数)存放文件属性
返回值:
成功:0
失败:-1 errno
获取文件大小:buf.st_size
获取文件类型:buf.st_mode
获取文件权限:buf.st_mode
符号穿透:stat会。lstat不会
23、link/unlink
隐式回收
24、目录操作函数:
DIR * opendir(char *name);
int closedir(DIR *dp);
struct dirent *readdir(DIR * dp);
struct dirent{
inode
char dname[256]
}
25、递归遍历目录: ls-R.c
1、判断命令行参数,获取用户要查询的目录名 argv[1]
argc == 1 -->./
2、判断用户指定的是否是目录 stat S_ISDIR(); -->封装函数 isFile
3、读目录:
opendir()
while(readdir()){
普通文件,直接打印
目录:
拼接目录访问绝对路径 sprintf(path,“%s%s”,dir,d_name)
递归调自己--> opendir(path) readdir closedir
}
closedir()
26、dup和dup2
int dup(int oldfd);
oldfd:已有文件描述符
返回:新文件描述符
27、fantl函数实现dup:
int fcntl(int fd,int cmd,。。。)
cmd:F_DUPFD
参3:被占用的,返回最小可用的
未被占用的,返回=该值的文件描述符
28、进程
程序:死的,只占用内存空间
进程: 活的。运行起来的程序。占用内存、CPU等系统资源
29、PCB进程控制块
进程id
文件描述符
进程工作目录位置
进程状态:初始态、就绪态、运行态、挂起态、终止态
*mask掩码
信号相关信息资源
用户id和组id
30、fork函数
pid_t fork(void)
创建子进程。父子进程各自返回。父进程返回子进程pid。子进程返回0
getpid();getppid();
循环创建n个子进程模型。每个子进程标识自己的身份
父子进程相同:
刚fork后。data段、text段、堆、栈、环境变量、全局目录、宿主目录位置、进程工作目录位置、信号处理方式
父子进程不同:
进程id、返回值、各自的父进程、进程创建时间、闹钟、未决信号集
父子进程共享:读时共享,写时复制
1、文件描述符(打开文件的结构体)
2、mmap建立的映射区(进程间通信共享)
31、gdb调试
设置父进程调试路径:set follow-fork-mode parent(默认)
设置子进程调试路径:set follow-fork-mode child
32、exec函数族:
使进程执行某一程序。成功无返回值,失败返回-1
int execlp(const char *file, const char *arg,...) 借助PATH环境变量寻找待执行程序
参1:程序名
参2:argv0
参3:argv1
....:argvN
。。。。
哨兵:NULL
int execl(const char *path,const char *arg,...) 自己指定待执行路径程序
int execvp();
ps ajx-->pid ppid gid sid
33、孤儿进程:
父进程先于子进程终止,子进程沦为“孤儿进程”,会被init进程领养
34、僵尸进程:
子进程终止,父进程尚未对子进程进行回收,在此期间,子进程论为“僵尸进程”
35、wait函数:
回收子进程退出资源,阻塞回收任意一个
pid_t wait(int *status)
参数:(传出)回收进程的pid
失败:-1,errno
函数作用1: 阻塞等待子进程退出
函数作用2: 清理子进程残留在内核的pcb资源
函数作用3: 通过传出参数,得到子进程结束状态
获取子进程正常终止值:
WIFEXITED(status)-->为真 --》调用WEXITSTATUS(status)--》得到子进程退出值
获取导致子进程异常终止信号:
WIFIGNALED(status)-->为真 --》调用WIERMSIG(status)--》得到导致子进程异常终止的信号编号
36、waitpid函数:
指定某一个进程运行,也可以设置非阻塞
waitpid(-1,&status,0)==wait(&status)
pid_t waitpid(pid_t pid, int *status, int optains)
参数:
pid:指定回收的子进程pid
>0:待回收的子进程pid
-1:任意子进程
0:同组的子进程
status:(传出)回收进程的状态
options:WNOHANG指定回收的方式为,非阻塞
返回值:
>0:表成功回收的子进程pid
0:函数调用时,参3指定了WNOHANG,并且,没有子进程结束
-1:失败。errno
总结:
wait、waitpid 一次调用,回收一个子进程
想回收多个:加while
37、进程间常用通信方式:特征:
管道:简单
信号:开销小
mmap映射:非血缘关系进程间
socket(本地套接字):稳定
38、管道
实现原理:内核借助环形队列机制,使用内核缓冲区实现
特质:1、伪文件
2、数据在管道中,只能单向流动
3、管道中的数据只能一次读取
局限性:1、自己写,不能自己读
2、数据不可以反复读
3、半双工通信
4、学院管子进程间可用
39、 pipe函数:
创建,并打开通道
int pipe(int fd[2]);
参数: fd[0]: 读端
fd[1]:写端
40、管道的读写行为
读管道:
1、管道有数据,read返回实际读到的字节数
2、管道无数据:(1)无写端,read返回0(类似读到文件尾)
(2)有写端,read阻塞等待
写管道:
1、无读端,异常终止(SIGPIPE导致的)
2、有读端: (1)管道已满,阻塞等待
(2)管道未满,返回写出的字节个数
41、pipe管道:
用于有血缘关系的进程间通信
父子进程间通信
兄弟进程间通信
42、fifo管道
无血缘关系进程间通信:
读端:open fifo O_RDONLY
写端:open fifo O_WRONLY
命名管道:mkfifo
43、void *mmap(void *addr, size_t length, int prot, int fd, off_t offset);
创建共享内存映射
参数:
addr:指定映射区的首地址。通常传NULL,表示让系统自动分配
length:共享内存映射区的大小
prot:共享内存映射区的读写特性。
PROT_READ、PROT_WRITE、PROT_READ|PROT_WRITE
flags:标注共享内存的共享属性。MAP_SHARED、MAP_PRIVATE
fd:用于创建共享内存映射区的那个文件的文件描述符
offset:偏移位置。需要是4k的整数倍
返回值:
成功:映射区的首地址
失败:MAP_FAILD,errno
44、 int munmap(void *addr, size_t length)
释放映射区
addr:mmap的返回值
length:大小
45、使用注意事项:
(1)用于创建映射区的大小为0,实际指定非0大小创建映射区,出“总线错误”
(2)用于创建映射区的文件大小为0,实际指定0大小创建映射区,出“无效参数”
(3)用于创建映射区的文件读写属性为,只读,映射区属性为 读、写。出“无效参数”
(4)创建映射区,需要read权限。当访问权限指定为MAP_SHARED,mmap的读写权限,应该《=文件的open权限。只写不行。
(5)文件描述符fd,在mmap创建映射区完成时即可关闭。后续访问文件,用地址访问
(6)offset必须是4096的整数倍(MMU映射的最小单位4k)
(7)对申请的映射区内存 ,不能越界访问
(8)munmap用于释放的地址,必须是mmap申请返回的地址
(9)映射区访问权限为“私有”MAP_PRIVATE,对内存所做的所有修改,只在内存有效,不会反映到物理磁盘上
(10)映射区访问权限为“私有”MAP_PRIVATE,只需要open文件时,有读权限,用于创建映射区即可
46、mmap函数的保险调用方式
(1)open(“文件名”,O_RDWR)
(2)mmap(NULL,有效文件大小,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0)
47、父子进程使用mmap进程间通信
父进程 先 创建映射区 : open(O_RDWR) mmap();
指定MAP_SHARED权限
fork()创建子进程
一个进程读,另一个进程写
48、无血缘关系进程间mmap通信:
两个进程打开同一个文件,创建映射区
指定flags为MAP_SHARED
一个进程写入,另外一个进程读出
【注意】:无血缘关系间通信。mmap:数据可以重复读取
fifo:数据只能一次读取
49、信号
共性:
简单、不能携带大量信息,满足条件才发送
信号的特质:信号是软件层面上的中断。一旦信号产生,无论程序执行到什么位置,必须立即停止运行,处理信号,处理结束,在执行后续指令
所有信号的产生及处理全部都是由【内核】完成的。
信号相关概念:
1、按键产生
2、系统调用产生
3、软件条件产生
4、硬件异常产生
5、命令产生
概念:
未决:产生与递达之间的状态
递达:产生并且送达到进程。直接被内核处理掉
信号处理方式:执行默认处理动作、忽略、捕捉(自定义)
阻塞信号集(子女好屏蔽字):本质:位图。用来记录信号的屏蔽状态。一旦被屏蔽的信号,在解除屏蔽前,一直处于未决态
未决信号集:本质:位图。用来记录信号的处理状态。该信号集中的信号,表示,已经产生,但尚未被处理。
信号四要素:
信号使用之前,应先确定其4要素,而后使用!!!
信号编号、信号名称、信号对应事件、信号默认处理动作
50、kill命令和kill函数
int kill (pid_t,int signum)
pid:>0:发送信号给指定进程
=0:发送信号给跟调用kill函数的那个进程处于同一进程组的进程
<-1:取绝对值,发送信号给改绝对值所对应的进程组的所有组员
=-1:发送信号给,有权限发送的所有进程
51、alarm函数
定时发送SIGALRM给当前进程
unsigned int alarm(unsigned int seconds)
seconds:定时秒数
返回值:上次定时剩余时间
无错误现象
time命令:查看程序执行时间。实际时间=用户时间+内核时间+等待时间--》优化瓶颈IO
52、setitimer函数:
int setitimer(int which,const struct itimerval *new_value, struct itimerval *old_value)
参数:
new _value:定时秒数
old_value:传出参数:上次定时剩余时间
返回值:
成功:0
失败:-1,errno
53、其他几个发信号函数:
int raise(int sig) ;
54、信号集操作函数:
sigset_t set:自定义信号集
sigemptyset( sigset_t *set):清空信号集
sigaddset(sigset_t *set,int signum);讲一个信号添加到集合中
sigdelset(sigset_t *set,int signum):从集合中移除
sigismember(const sigset_t *set,int signum):判断一个信号是否在集合中
55、设置信号屏蔽字和解除屏蔽:
int sifprocmask(int how, const sigset_t *set,sigset_t *oldset)
how: SIG_BILOCK 阻塞
SIG_UNBLOCK 取消阻塞
SIG_SETBLOCK 用自定义的set替换mask
set: 自定义set
oldset:旧有的mask
56、查看未决信号集
int sigpending(sigset_t *set)
set:传出的未决信号集
57、信号捕捉:
signal();
sigaction();
58、信号捕捉特性:
(1)捕捉函数执行期间,信号屏蔽字由mask--》sa_mask,捕捉函数执行结束,恢复回mask
(2)捕捉函数执行期间,本信号自动被屏蔽(sa_flags=0)
(3)捕捉函数执行期间,被屏蔽信号多次发送,解除屏蔽后只处理一次
借助信号完成子进程回收
59、守护进程:
daemon进程:通常运行与操作系统后台,脱离终端控制。一般不予用户直接交互。周期性的等待某个事情发生或周期性执行某一动作。不受用户登录注销影响。通常以d结尾的命名方式
60、守护进程创建方式:
(1)fork子进程,让父进程终止
(2)子进程调用setsid(),创建新会话
(3)通常根据需要,改变工作目录位置chdir()
(4)通常根据需要,重设mmask文件权限掩码
(5)通常根据需要,关闭/重定向 文件描述符
(6)守护进程,业务逻辑。while()
61、线程概念:
进程:有独立的进程地址空间,有独立的pcb 分配资源的最小单位
线程:有独立的pcb,没有独立的进程地址空间
ps -Lf 进程id ---》线程号。LWP--》cpu执行的最小单位
62、线程共享:
独享 栈空间(内核栈、用户栈)
共享: ./text./date
63、线程控制原语 :
pthread_t pthread_self(void): 获取线程id。线程id是地址进程内部空间,用来标识线程身份的id
返回值:本线程id
int pthread_create(pthread_t *tid, pthread_attr_t *attr,void *(*start_rountn)(void *),void * arg)
参1:传输参数,表新创建的子线程id
参2:线程属性,传NULL表使用默认属性
参3:子线程回调函数。创建成功,pthread_create函数返回时,该函数会被自动回调
参4:参3的参数。没有的话,传NULL
返回值:成功0
失败:errno
循环嵌套N个子进程:
for(int i0;i<5;i++)
pthread_create(&tid,NULL,tfn,(void *)i);将int类型i,强制转换成void *,传参
void pthread_exit(void *retval):退出当前线程
retval:退出值。无退出值时,NULL
exit():退出当前进程
return:返回到调用者那里去
pthread_exit:退出当前线程
int pthread_join(pthread_t thread, void **retval):回收线程
thread:待回收的线程id
retval:传出参数。回收的那个线程的退出值
返回值:成功0
失败:errno
int pthread_datach(pthread_t thread):设置线程分离
thread:待分离的线程id
返回值:成功0
失败:errno
int pthread_cancel(pthread_t thread):杀死一个线程。需要到达取消点(保存点)
thread:待杀死的线程id
返回值:成功0
失败:errno
如果子线程没有到达取消点,那么 pthread_cancel无效。
我们可以在程序中手动添加取消点,使用pthread_testcancel()
成功被pthread_cancel()杀死的线程,返回-1,使用pthread_join回收
线程控制原语 进程控制原语
pthread_create() fork()
pthread_self() getpid()
pthread_exit() exit()\return()
pthread_join() wait()/waitpid()
pthread_cancel() kill()
pthread_datach()
64、线程属性
设置分离属性:
pthread_attr_t attr: 创建一个线程属性结构体变量
pthread_attr_init(&attr):初始化线程变量
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED)设置线程属性为分离态
pthread_create(&tid,&attr,tfn,NULL)借助修改后的设置线程属性创建为分离态的新线程
pthread_attr_init(&attr)销毁线程属性
65、线程同步:
协同步调,对公共区域数据按序访问。防止数据混乱,产生与时间相关的错误
66、锁的使用
建议锁!对公共数据进行保护。所有线程应该在访问公共数据前先拿锁在访问。但,锁本身不具备强制性
67、使用mutex(互斥量、互斥锁)一般步骤
(1)pthread_mutex_t lock:创建锁
(2)pthread_mutex_init:初始化
(3)pthread_mutex_lock:加锁
(4)访问公共数据(stdout)
(5)pthread_mutex_unlock():解锁
(6)pthread_mutex_destory():销毁锁
初始化互斥量:
1、 pthread_mutex_init(&mutex,NULL);动态初始化
2、 pthread_mutex_t mutex=PTHEREAD_MUTEX_INITALIZER;静态
注意事项:
尽量保证锁的粒度,越小越好。(访问共享数据前,加锁。访问结束【立即】解锁)
互斥锁:本质是结构体,我们可以看做是整数。初值为1(pthread_mutex_init()函数调用成功)
加锁:--操作,阻塞线程
结束:++操作,唤醒阻塞在锁上的线程
try锁:尝试加锁,成功--,失败,返回。同时设置错误号EBUSY
restrict:关键字:
用来限定指针变量。被该关键字限定的指针变量所指向的内存操作,必须由本指针完成
68、死锁:
是使用锁不恰当导致的现象
1、对一把锁反复lock
2、两个线程,各自持有一把锁,请求另一把
69、读写锁:
锁只有一把。以读方式给数据加锁--读锁。以写方式给数据加锁--写锁
读共享,写独占
写锁优先级高
相较于互斥量而言,当读线程多的时候,提高访问效率
pthread_rwlock_t rwlock;
pthread_rwlock_init(&relock,NULL);
pthread_rwlock_rdlock(&rwlock)
pthread_rwlock_rdlock(&rwlock)
pthread_rwlock_unlock(&rwlock)
pthread_rwlock_destory(&rwlock)
70、条件变量
本身不是锁!但是通常结合互斥锁来使用Mutex
pthread_cond_t cond;
初始化条件变量:
1、 pthread_cond_init(&cond,NULL);动态初始化
2、 pthread_cond_t cond=PTHEREAD_COND_INITALIZER;静态初始化
pthread_cond_signal():唤醒阻塞在条件上的(至少)一个线程
pthread_cond_broadcast():唤醒阻塞在条件变量上的所有线程
【要求,能够借助条件变量,完成生产者消费者模型】
71、信号量
应用于线程、进程间同步
相当于初始化值为N的互斥量。N值,表示可以同时访问共享数据区的线程数
函数:
sem_t sem:定义类型
int sem_init(sem_t *sem,int pshared,unsigned int value);
参数:
sem:参数量
pshared: 0:用于线程间同步
1:用于进程间同步
value:N值。(指定同时访问的线程数)
sem_init(&sem,0);
sem_destroy();
sem_wait(); 一次调用,做一个--操作。当信号值为0时,再次--就会阻塞
sem_post(); 一次调用,做一个++操作。当信号值为N时,再次++就会阻塞