Linux 系统笔记
Linux环境搭建以及常用命令
Linux常见目录框架
dev/ 设备文件 //linux下一切皆文件
bin/ 系统程序
sbin/ 管理员系统程序
lib/ 系统程序库文件
etc/ 系统程序和大部分应用程序的全局配置文件
ust/
Linux常用命令
打开终端:ctrl+alt+t
关闭终端:ctrl+alt+q
放大:ctrl+alt++
缩小:ctrl+-
终端标识符:用户名@计算机名:-$:
man:查询指令和函数
man:查询指令和函数
ls:查看当前路径下文件
ls:查看当前路径下文件
ls -s:查看文件的详细信息
- 第一位代表文件类型:
-:普通文件
l:链接文件————快捷方式
d:目录
b:块设备————U盘 硬盘
p:管道————进程直接的通信方式
c:字符设备
s:套接字————进程之间进行通信的方法 - 第2-4位:代表文件的拥有者对文件拥有的权限
r:可读————4
w:可写————2
x:可执行——1
如果一个权限没有就使用 - 表示
创建文件时系统不会默认给最高权限,命令umask,0002:0:代表八进制;0:第一个用户;0:第二个用户;2:代表第三个用户 - 第5-7位:代表同组用户对文件拥有的权限
- 第8-10:代表其它用户对文件拥有的权限
cd:切换到指定目录
cd 路径
cd .:切换到当前目录
cd ..:切换到上一级目录
cd -:切换到上一次所在目录
cd /:切换到根目录
tab键:自动补全,当前路径下不能有相同字符开头的文件,否则不补全
*:通配符,代表所有
mv:删除文件或目录 删除目录加 —r
mkdir:创建目录
mkdir -m 权限 目录名
mkdir -p 多级嵌套创建目录
touch:创建文件
cp:复制,复制目录加 -r
mv:修改文件名或移动文件位置
chmod:修改文件/目录权限
chmod 权限(4,2,1的组合) 文件/目录名
cat:再不打开文件的同时查看文件内容
ifconfig:查看当前网络信息
ping 域名:测试系统是否和外网相同
ln -s 源文件 链接文件 创建链接文件
打包解压
打包:tar -cvf xxx.tar xxx(目录)
解压:tar -xvf xxx.tar -C 路径
history:查看系统里执行的历史命令
find 路径 -name 文件名:按文件名检索
grep:检索文件里的关键字
grep -n "关键字" 文件名:把文件里哪些行包含关键字都检索出来
grep -v "关键字" 文件名:反向查询,除了关键字其他都检索出来
echo:回显
echo 内容 >> 文件名:将内容写到文件里
echo 内容 > 文件名:先将文件内容清空在将内容写进文件
chown:改变文件属性
chown (-R —h)owner file
-R:递归操作
-h:改变链接文件的属主时不影响该链接指向的目标文件
软件安装
sudo apt-get install xxx:安装xxx软件,在线安装
sudo apt-get rmove xxx:卸载xxx软件
sudo apt-get update:更新本地的源
sudo apt-get upgrade:更新本地的软件
dpkg -i xxx.deb:离线安装deb包
主函数
int main(int argc,char *argv[])
argc:代表传递参数的个数
argv:代表你具体传递的参数
argv[0]:代表执行命令
argv[1]:第一个参数
Linux常用工具
vim
sudo apt-get install vim
vim 文件名:文件存在就打开,不存在就创建并打开
vim 文件名 行号:打开文件并且光标跳到指定行
vim的四种模式:
- 命令行模式
- 复制:(n)yy n表示从光标当前所在行开始往下复制多少行
- 粘贴:p
- 删除:(n)dd n表示从光标当前所在行开始往下删除多少行
- 撤销:u
- gg:从光标所在位置跳转到代码的开头
- G:从光标所在位置跳转到代码的结尾
- gg=G:代码自动对齐
- 插入模式
- 在命令行模式按i进入插入模式
- 底行模式
- 进入底行模式:shift + :
- w:保存不退出
- w!:强制保存
- q:不保存退出,如果文件内容有改动会无法退出
- q!:强制退出不保存
- wq:保存并退出
- x:如果修改了就保存退出,如果没有就直接退出
- /关键字:查找关键字,如果有就高亮显示(前提是配置了高亮显示)
- noh:去除高亮
- %s/原字符串/替换的字符串/g:字符串替换
- 可视模式
- 命令行模式下按v进入可视模式
- d:删除
- y:复制
- x:剪切
vim的配置文件位置:/etc/vim/vimrc
sudo gedit /etc/vim/vimrc
编译工具
编译工具:gcc:把代码翻译成计算机能够识别的二进制文件
一个.c文件从编写到执行的四个过程
- 编译预处理
- gcc -E xxx.c -o xxx.i:处理宏定义,就是以#开头的
- 编译
- gcc -S xxx.i -o xxx.s:进一步把编译预处理后的文件做语法检查
- 汇编
- as xxx.s -o xxx.o:将汇编代码翻译成所对应的机器指令,一条汇编代码对应一条机器指令
- 链接
- gcc xxx.o -o xxx:找到真正的库函数(头文件只告诉了头文件的路径,而真正的函数是封装在库里的)
静态库与动态库
库就是一个可以反复使用的特殊文件,文件包含真正的变量,结构体,函数体等,供开发人员使用
好处是最大程度的保护了程序员的利益
静态库
静态库后缀是.a
gcc xxx.c -o xxx -l+路径
库名:libxxx.a
gcc -c xxx.c //只编译不链接生成产物是.o
ar -rc libxxx.a xxx.o //打包生成静态库
动态库
动态库后缀是.so
gcc -c xxx.c -fpic
gcc -fpic -shared xxx.o libxxx.so
gcc xxx.c -o -lxxx
gdb调试工具
gcc -g xxx.c -o xxx:xxx为可编译文件,他编译出来的代码要比不加-g的大,大出来的部分就是gdb的调试信息
gdb的使用
- gdb 文件名:进入gbd
- r:开始运行
- l:查看源码信息
- break/b:设置断点
- b:行号/函数名
- info b:查看断点信息
- printf/p:查看变量当前的值
- n:单步运行:遇到函数不会跳到函数内部,而是直接拿到函数的运行结果
- s:单步运行:遇到函数,跳到函数的内部去运行,在函数内运行完才结束
- quit:退出
makefile
makefile:管理工程代码的工具
文件名必须是makefile/Makefile
否则用:make -f 文件名
makefile里的变量没有类型之分,直接定义,使用的时候:$(变量名)
make
目标:依赖
编译指令(编译指令前必须添加至少一个tab键)
伪目标:
指令
make clear
clear:
rm -rf 要删除的文件名
make echo
echo:
echo $(变量名)/@echo $(变量名)
makefile里的特殊变量
makefile里的注释为:#
$@:目标文件
$^:依赖文件(所有)
$<:依赖文件(第一个)
makefile里的通配符:%
makefile里的常用函数
函数功能:在指定路径下查找指定文件
函数原型:$(wildcard 路径)
函数返回值:成功就返回所有指定的文件
函数功能:去除文件名前的路径
函数原型:$(notdir $(承接上个函数结果的变量))
函数返回值:返回文件名
函数功能:把文件名替换成指定的文件名
函数原型:$(patsubst 文件类型,替换之后的类型,源文件路径)
函数返回值:返回替换后的文件
文件操作
标准IO有缓存,文件IO无缓存
每运行一个进程,系统默认打开三个流:
- stdin——0:有缓存——对应键盘
- stdout——1:有缓存——对应显示屏
- stderr——2:无缓存——对应显示屏
缓存区输出条件:
- 遇到\n
- 程序结束
- fflush()
- 全缓存 行缓存,行缓存大小1024
标准IO操作函数
- fopen——打开文件
FILE fopen(文件路径,打开模式)
FILE名称=fopen(文件路径,打开模式)
模式:- “r”:只读,文件不存在,打开失败
- “w”:只写,文件不存在,创建打开,存在,清空写
- “a”:只写,文件不存在,创建打开,存在,追加写
- “r+”:读写,文件不存在,打开失败
- “w+”:读写,文件不存在,创建打开,存在,清空写
- “a+”:读写,文件不存在,创建打开,存在,追加写
函数返回值:成功返回名称,失=失败返回NULL
- perror——打印离他最近的函数执行失败的原因
perror(const char *s)
s:错误标题 - fclose——关闭文件
int fclose(fopen的名称)
返回值:关闭成功返回0,失败返回-1 - fputc——单字符写入
int fputc(char类型单字符,fopen的名称)
返回值:返回写入的字符,失败返回-1 - fgetc——单字符读取
int fgetc(fopen的名称)
返回值:成功返回取得的单个字符,失败返回-1 - fputs——字符串写入
char *fputs(要写入的字符串的首地址,fopen的名称)
返回值:成功返回写入的字节大小,失败返回-1 - fgets——字符串的读取
char *fgets(读取到的内容存放的地址,读取多大,fopen的名称)
返回值:成功返回获取的字符串,失败返回NULL - feof——判断文件是否到达文件末尾
feof(fp):到结尾返回非0值,否则返回0
不会造成光标偏移 - fwrite——块写
fwrite(写入到文件中的首地址,一次写入多大字节,写入几次,fopen名称)
返回值:成功返回写入字节大小,失败返回-1 - fread——块读
fread(读取到的内容存放的首地址,一次都多大字节,读取几次,fopen名称)
返回值:成功返回读取字节大小,失败返回-1 - rewind——使光标回到文件开头
rewind(fopen的名称)
返回值:无 - fseek——光标偏移函数
fseek(fp,偏移量,偏移量的起始位置)
偏移量:+表示往文件末尾便宜,-表示往文件起始位置偏移
起始位置:0——SEEK_SET:文件开头,1——SEEK_CUR:当前位置,2——SEEK_END:文件末尾
返回值:成功返回0,失败返回-1 - ftell——计算文件当前位置到文件开头的偏移量
tell() - fprintf——格式化写入
fprintf(fopen名称,"%d",a);
返回值:成功返回0,失败返回-1 - fscanf——格式化读取
fscanf(fopen名称,"%d",&a);
返回值:成功返回0,失败返回-1
fprintf和fscanf格式必须一至才能准确读取 - sprintf——格式化复制
int sprintf(要复制内容的保存位置,要操作的格式,要操作的变量)
返回值:成功返回0,失败返回-1 - atoi——把字符串转换成整型
int atoi(要转换的变量)
返回值:成功返回转换之后的类型,失败返回-1
文件IO操作函数
-
open——打开文件
int open(要打开的文件,打开方式)
头文件:include <sys/types.h>
include <sys/stat.h>
include <fcntl,h>
打开方式 描述 O_RDONLY 只读 O_WRONLY 只写 O_RDWD 可读可写 O_APPEND 追加写 O_CREAT 可读可写int open(要打开的文件,打开方式,文件权限(如:0666)) O_EXCL 如果文件存在就报错,一般和O_CREAT一起 O_TRUNC 清空文件内容 同时使用多个 如O_CREAT|O_EXCL 返回值:成功返回文件名,失败返回-1
-
close——关闭文件
int close(文件名)
头文件:#include <unistd.h>
返回值:成功返回0,失败返回-1 -
read——从文件里读取内容
ssize_t read(文件名,要读入的缓冲区(提前申请好),读取的大小)
头文件:#include <unistd.h>
返回值:成功返回读取到的字节数,失败返回-1 -
write——向文件里写入内容
ssize_t write(文件名,写入的空间(提前申请好),写入的内容大小)
头文件:#include <unistd.h>
返回值:成功返回写入的字节数,失败-1 -
lseek——移动光标位置
off_t lseek(文件名,偏移量,偏移量的起始位置)
头文件:#include <sys/types.h>/#include <unistd.h>
返回值:成功返回偏移量的位置,失败返回-1
时间编程
和时间有关的指令
- date——显示当前时间
date -R——以字符串的形式显示
date -u——世界标准时间 - cal——显示当前的日历时间
cal 月 年——查看指定的时间
时间编程的API
struct tm
{
int tm_sec;/* 秒:取值区间为[0,59] */
int tm_min;/* 分:取值区间为[0,59] */
int tm_hour;/* 时:取值区间为[0,23] */
int tm_mday;/* 一个月中的日期:取值区间为[1,31] */
int tm_mon; /* 月份(从一月开始,0代表一月) :取值区间为[0,11] */
int tm_year;/* 年份:其值等于实际年份加上 1900*/
int tm_wday;/* 星期:取值区间为[0,6],其中0代表星期天,1代表星期一,以此类推 */
int tm_yday;/* 从每年的1月1日开始的天数:取值区间为[0,365],其中0代表1月1日,1代表1月2日,以此类推*/
int tm_isdst;/* 夏令时标识符,实行夏令时的时候,tm_isdst为正,不实行夏令时的进候,tm_isdst为0;不了解情况时,tm_isdst()为负*/
};
头文件:#include <time.h>
- time——获取当前的日历时间
time_t time(一般填NULL)
返回值:成功返回当前日历时间,失败返回-1 - gmtime——获取标准时间(格林威治时间)
struct tm *gmtime(待转化的日历时间)
返回值:成功返回世界标准时间,失败返回NULL - locatime——获取本地时间
struct tm *localtime(待转化的日历时间)
返回值;成功返回本地时间,失败返回NULL - asctime——以字符串的形式去获取时间
char *asctime(获取本地/标准时间函数的返回值)
返回值:成功返回字符串显示的时间,失败返回NULL - ctime——直接把日历转换成本地时间
char *ctime(待转化的日历时间)
返回值:成功返回本地时间,失败返回NULL - strftime——将struct tm格式的时间按照对应格式转化为字符串
size_t strftime(格式化写入的数组首地址,写入的数组大小,format,本地时间/标准时间函数的返回值)
返回值:成功返回格式化的时间,失败返回-1
format:相当于printf的"",以下为格式控制符
说明符 | 替换为 | 实例 |
---|---|---|
%a | 缩写的星期几名称 | Sun |
%A | 完整的星期几名称 | Sunday |
%b | 缩写的月份名称 | Mar |
%B | 完整的月份名称 | March |
%c | 日期和时间表示法 | Sun Aug 19 02:56:02 2012 |
%d | 一月中的第几天(01-31) | 19 |
%H | 24 小时格式的小时(00-23) | 14 |
%I | 12 小时格式的小时(01-12) | 05 |
%j | 一年中的第几天(001-366) | 231 |
%m | 十进制数表示的月份(01-12) | 08 |
%M | 分(00-59) | 55 |
%p | AM 或 PM 名称 | PM |
%S | 秒(00-61) | 02 |
%U | 一年中的第几周,以第一个星期日作为第一周的第一天(00-53) | 33 |
%w | 十进制数表示的星期几,星期日表示为 0(0-6) | 4 |
%W | 一年中的第几周,以第一个星期一作为第一周的第一天(00-53) | 34 |
%x | 日期表示法 | 08/19/12 |
%X | 时间表示法 | 02:50:06 |
%y | 年份,最后两个数字(00-99) | 01 |
%Y | 年份 | 2012 |
%Z | 时区的名称或缩写 | CDT |
%% | 一个 % 符号 | % |
文件属性和目录操作
文件属性
文件属性的核心结构体
struct stat
{
dev_t st_dev; /*如果是设备,返回文件使用的设备号,否则为 0*/
ino_t st_ino; /* 索引节点号 */
mode_t st_mode; /* 文件类型 */
nlink_t st_nlink; /* 文件的硬连接数 */
uid_t st_uid; /* 所有者用户识别号*/
gid_t st_gid; /* 组识别号 */
dev_t st_rdev; /* 设备类型*/
off_t st_size; /* 文件大小,字节表示 */
blksize_t st_blksize; /* 系统每次按块Io操作时块的大小(一般是512或1024)*/
blkcnt_t st_blocks; /*块的索引号 */
time_t st_atime; /* 最后访问时间,如read*/
time_t st_mtime; /* 最后修改时间*/
time_t st_ctime; /* 创建时间 */
};
获取文件属性的函数
- stat——获取文件的属性
int stat(文件,文件属性的核心结构体)
头文件:#include <sys/types.h>/#include <sys/stat.h>/#include <unistd.h>
返回值:成功返回0,失败返回-1 - fstat——获取文件的属性
int fstat(文件描述符,文件属性的核心结构体)
头文件:#include <sys/types.h>/#include <sys/stat.h>/#include <unistd.h>
返回值:成功返回0,失败返回-1
stat只需要提供一个文件路径,fstat需要使用open函数打开文件,然后用open返回的文件描述符来获取文件的属性 - lstat——获取文件的属性
int lstat(文件描述符,文件属性的核心结构体)
头文件:#include <sys/types.h>/#include <sys/stat.h>/#include <unistd.h>
返回值:成功返回0,失败返回-1
stat不可查看链接文件的属性,lstat可以查看链接文件的属性
判断文件类型
宏 | 描述 |
---|---|
S_ISLNK(mode) | 判断是否是符号链接 |
S_ISREG(mode) | 判断是否是普通文件 |
S_ISDIR(mode) | 判断是否是目录 |
S_ISCHR(mode) | 判断是否是字符型设备 |
S_ISBLK(mode) | 判断是否是块设备 |
S_ISFIFO(mode) | 判断是否是命名管道 |
S_ISSOCK(mode) | 判断是否是套接字 |
判断文件是否存在,以及文件的各个权限是否存在
access——判断文件是否存在,以及文件的各个权限是否存在
int access(要判断的文件,int mode)
头文件:#include <unistd.h>
返回值:成功返回0,失败返回-1
mode:
R_OK:读权限
W_OK:写权限
X_OK:执行权限
F_OK:文件是否存在
目录操作
- mkdir——创建目录
int mkdir(文件路径,权限(如:0777权限这里要注意给的权限里要包含x执行权限))
头文件:#include <sys/stat.h>/#include <sys/types.h>
返回值:成功返回0,失败返回-1 - rmdir==rm——删除目录
int rkdir(文件路径)
头文件:#include <unistd.h>
返回值:成功返回0,失败返回-1 - getcwd==pwd——显示当前绝对路径
char *getcwd(保存当前目录的缓存区,缓存区大小(最大255字节))
头文件:#include <unistd.h>
返回值:成功返回当前路径,失败返回NULL - chdir==cd——切换路径
int chdir(目标路径)
头文件:#include <unistd.h>
返回值:成功返回0,失败返回-1 - chmod——更改权限
int chmod(文件路径,权限)
头文件:#include <sys/types.h>/#include <sys/stat.h>
返回值:成功返回0,失败返回-1 - system——系统命令
int system(要执行的命令)
头文件:#include <stdlib.h>
返回值:成功返回0,失败返回-1
目录操作的核心结构体
存储目录中的文件信息(文件名、扩展名等等)
#include <dirent.h>
struct dirent
{
long d_ino; /* inode number 索引节点号 */
off_t d_off; /* offset to this dirent 在目录文件中的偏移 */
unsigned short d_reclen; /* length of this d_name 文件名长 */
unsigned char d_type; /* the type of d_name 文件类型 */
char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */
}
d_tyep 有 8 种类型:
(1)、 DT_BLK This is a block device. 设备
(2)、 DT_CHR This is a character device. 符设备
(3)、 DT_DIR This is a directory. 录
(4)、 DT_FIFO This is a named pipe (FIFO). 道
(5)、 DT_LNK This is a symbolic link. 链接
(6)、 DT_REG This is a regular file. 通文件
(7)、 DT_SOCK This is a UNIX domain socket. 接字
(8)、 DT_UNKNOWN The file type is unknown. 未知类型
- opendir——打开指定的目录
DIR *opendir(要打开的目录名)
头文件:#include <sys/types.h>/#include <dirent.h>
返回值:成功返回一个指向DIR的指针,失败返回NULL - closedir——关闭打开的目录
int closedir(要关闭的目录)
头文件:#include <sys/types.h>/#include <dirent.h>
返回值:成功返回0,失败返回-1 - dirent——读取目录里的内容
struct dirent *readdir(opendir函数的返回值)
返回值:成功返回指向struct dirent指针,失败返回NULL - strstr——在字符串中查找特定字符串第一次出现的位置
char *strstr(源字符串,特定字符串)
头文件:#include <string.h>
返回值:成功返回查找到的指向字符串的指针,失败返回NULL - rewinddir——将目录的目录流拉到开头
void rewinddir(opendir的返回值)
头文件:#include <sys/types.h>/#include <dirent.h>
返回值:无 - seekdir——把目录流移动到指定位置
void seekdir(opendir函数的返回值,要移动的位置)
头文件:#include <dirent.h>
返回值:无 - telldir——获取当前目录流的位置
off_t tellir(opendir函数的返回值)
头文件:#include <dirent.h>
返回值:成功返回目录流的下一个位置,失败返回-1
进程初步
进程即使系统运行的最小单位
进程是程序的一次执行过程,他是一个活的,他和代码时刻都消耗计算机的资源
进程的特性
- 独立性:每一个进程的空间都是独立的,每运行一个进程系统都会分配4G的虚拟内存空间
- 并发性:一次可以运行多个进程,各自完成不同的任务
- 异步性:由于进程间的相互制约,是进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推进
- 动态性:进程的实质是程序的一次执行过程,进程是动态产生,动态消亡的
进程的三态
- 就绪态:进程已具备执行的一切条件,正等待分配CPU的处理时间片
- 等待态:进程正在等待某些事件,当前不能分配时间片,进程不能使用CPU,若等待事件发生(等待的资源分配到)则可将其唤醒,变成就绪态
- 执行态:该进程正在运行,即进程正在占用CPU,在任何时候都只有一个进程
如何区分管理进程
PID:相当于进程的身份证号 取值范围32位是32767,64位为2^22,1-300已经被系统占用
特殊进程
- 0号进程:引导进程,引导内核的一个进程
- 1号进程:系统起来之后运行的第一个进程,这里也叫init进程
- 僵尸进程:已经不再给系统做任何贡献,但是还保留着系统的资源,对系统的危害很大,因为系统的资源是有限的
- 孤儿进程:父进程先于子进程退出,此时子进程会被init进程收养,init进程给他收尸
进程相关的命令
-
ps -ef:查看进程的状态
标志 描述 UID 用户名 PID 子进程的ID PPID 父进程的ID TTY 进程的状态 CMD 命令名称 %CPU CPU使用率 %MEN 内存使用率 STAT 进程运行的状态 START 命令启动的时间 TIME 进程的总执行时间 VSZ 进程确保的虚拟内存大小 RSS 实际使用的内存量 -
top:可以动态的查看进程的状态
-
ps -aux:显示进程的详细信息
stat 描述 S 睡眠 R 运行(执行或即将运行状态) D 不可中断的睡眠(等待),通常等待输入回输出完成 T 停止,通常是被shell或调试器控制停止 N 低优先级任务 Z 僵尸进程 X 死进程 s 进程是会话期首进程 + 后台进程,和用户交互的任务 | :进程是多线程的 < :高优先级任务
父进程和子进程
父进程:创建子进程的进程
子进程:被父进程创建的进程
可以通过ctrl+c或者kill -9 pid来杀死一个进程
进程的操作函数
- getpid——获取自己的PID
pid_t getpid(void)
头文件:#include <sys/types.h>/#include <unistd.h>
返回值:成功返回自己的PID,失败返回-1 - getppid——获取父进程的PID
pid_t getppid(void)
头文件:#include <sys/types.h>/#include <unistd.h>
返回值:成功返回父进程的PID,失败返回-1 - fork——创建子进程
pid_t fork(void)
头文件:#include <unistd.h>/#include <sys/types.h>
返回值:在父进程中返回子进程的PID,在子进程中返回0,失败返回-1
ps:一旦创建成功,那么子进程和父进程就同时运行,但互不干扰,子进程会复制父进程的资源。然后他们各自使用各自的空间变量,他们的运行顺序不确定 - vfork——创建子进程
pid_t vfork(void)
头文件:#include <unistd.h>/#include <sys/types.h>
返回值:在父进程中成功返回子进程的PID,在子进程中返回的PID是0,失败返回-1
ps:一但子进程创建成功,那么一定是先运行子进程,并且是子进程结束了,父进程才会得到运行,也就是说,子进程会阻塞父进程,资源是共享的
子进程退出的时候一定要使用exit() - wait——等待子进程退出做清理工作
pid_wait(一般填写NULL)
头文件:#include <sys/types.h>/#include <sys/wait.h>
返回值:成功返回结束的那个子进程的PID,失败返回-1 - waitpid——等待清理你指定的那个子进程
pid_t waitpid(要清理的子进程PID,一般写NULL,0(阻塞父进程,同wait)/WNOHANG(若由pid指定的子进程不立即可用,则waitpid不阻塞,此时返回0))
头文件:#include <sys/types.h>/#include <sys/wait.h>
返回值:成功返回结束的那个子进程的PID,失败返回-1 - _exit——进程正常退出的标准
void_exit(一般写0即可)
头文件:#include <stdlib.h>
返回值:无
_exit(0)与exit(0)的区别:exit在结束进程时回去清理缓冲区里的内容,然后结束进程;_exit(0)在结束时不会清理缓冲区里的内容,会直接把进程结束掉。一般都是使用exit(0)
exec函数族:这些函数的功能都是实现在一个进程里去执行另一个进程的功能,但是他会覆盖原来的那个进程
exec 是一个函数族,它包括了多个不同的函数,如 execl、execv、execle、execve、execlp、execvp
- execl——在一个进程里去执行其他进程
int execl(要执行这个进程的文件路径(最好写绝对路径),执行这个进程所需要的指令,最后一个参数必须使用NULL)
头文件:#include <unistd.h>
返回值:成功返回0,失败返回-1 - execlp——在一个进程里去执行其他进程
int execlp(要执行这个进程的文件路径(系统会默认去环境变量查找,如果找不到就去当前目录找,找不到就报错),执行这个进程所需要的指令,最后一个参数必须使用NULL)
头文件:#include <unistd.h>
返回值:成功返回0,失败返回-1
信号以及管道
信号
进程之间为什么要进行通信:
- 数据传输
- 时间控制
- 资源共享
进程通信的方法:
- 信号:软中断模拟机制:类似于通知
- 管道:进程间直接通信的最简单的方法:可以进行数据传输,具有单向导通性以及阻塞
- 共享内存:多个进程共享一块数据可以随时读取以及更改
- 消息队列:进程间通信最合理的方法之一:最符合通信思想,单纯收发数据
- 信号量集:用来解决进程间资源抢占问题
- 套接字:网络中进程通信方法
信号通信
信号通信就是给进程发送一个进程
linux信号分为两部分:
- 1-31时unix信号:他是非实时信号:非实时信号没有排队机制,后来信号会打断正在执行的信号,后来的信号执行完后再跳转到原来的信号继续执行
- 34-64是自己拓展的实时信号:实时信号谁先来的先处理谁
重要的信号:
- 2信号:Ctrl + c
- 3信号:Ctrl + \
- 9信号:杀死一个进程
- 19信号:暂停信号
- 18信号:继续信号
- 17信号:专门用于父子进程,
产生条件:- 子进程结束
- 子进程遇到19信号,暂停
- 子进程从暂停状态回复,遇到18信号
- 14信号:闹钟信号
信号操作函数:
-
signal——捕获指定信号
sighandler(要捕获的信号,对此信号的处理方式(1.SIG_IGN忽略处理SIGKILL和SIGSTOP信号不能忽略;2.SIG_DFL默认处理,即交给内核,大部分都是杀死进程;3.自己封装函数来处理函数原型typedef void(*sighander_t)(int)))
头文件啊:#include <signal.h>
返回值:成功返回,失败返回SIG_ERR -
kill——向执行进程发送指定信号
int kill(进程,信号)
头文件:#include <sys/types.h>/#include <signal.h>
返回值:成功返回0,失败返回-1 -
raise——给本进程发送信号
int raise(信号)
头文件:#include <sys/types.h>/#include <signal.h>
返回值:成功返回0,失败返回-1 -
alarm——设置时间值,到达时间产生SIGALRM——14信号,不捕捉的时候默认终止进程
unsigned int alarm(设置的产生闹钟信号的时间)
头文件:#include <unistd.h>
返回值:如果调用alarm()之前,进程已经设置了闹钟时间,成功返回剩余闹钟时间,失败返回0 -
pause——阻塞当前进程,直到捕捉到一个信号
int pause(void)
头文件:#include <unistd.h>
返回值:成功返回0,失败返回-1 -
glob——在指定的路径下查找指定的文件
int glob(要查找的路径,一般写0,NULL,找到结果保存的位置(结构体))
结构体:typedef struct { __size_t gl_pathc;/*指定文件匹配的数量*/ char **gl_pathv;/*指定匹配文件的文件名*/ } glob_t;
头文件:#include <glob.h>
返回值:成功返回0,失败返回-1
管道
进程间通信的方法之一,也是最简单的通信方法
无名管道
在创建时没有名字,专用于父子进程之间
- pipe——创建无名管道
int pipe(管道的两端:pipefd[2](fd[0]读 fd[1]写))
头文件:#include <unistd.h>
返回值:成功返回0,失败返回-1
ps:一旦创建成功就处于打开状态
有名管道
在创建时有名字,用于任意进程之间
- mkfifo——创建有名管道
int mkfifo(管道名(带路径),文件权限)
头文件:#include <sys/stat.h>/#include <sys/types.h>
返回值:成功返回0,失败返回-1
ps:创建成功后使用时必须先打开 - unlink——删除管道
int unlink(管道名(带路径))
头文件:#include <unistd.h>
返回值:成功返回0,失败返回-1
共享内存&消息队列&信号量集
共享内存
终端指令:
ipcs -m 查看共享内存
ipcs -q 查看消息队列
ipcs -s 查看信号量集
ipcrm -m xxxid号 删除指定的共享内存
ipcrm -q xxxid号 删除指定的消息队列
ipcrm -s xxxid号 删除指定的信号量
共享内存的方法
- 先创建一个键值
- 创建/获取一个共享内存
- 把共享内存映射到自己的进程里
- 对这个共享内存进行读写操作
- 解除映射
- 删除共享内存
函数:
- ftok——创建键值
key_t ftok(指定的文件,子序列号(取值范围0-255))
头文件:#include <sys/types.h>/#include <sys/ipc.h>
返回值:成功返回创建的键值,失败返回-1 - shmget——创建/获取共享内存的id
int shmget(键值,共享内存的大小,操作(IPC_creat|066))
头文件:#include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h>
返回值:成功返回共享内存的id,失败返回-1 - shmat——映射共享内存到自己的进程里
void *shmat(共享内存的id,共享内存的资质映射的位置(NULL:系统自动分配,默认0:可读可写))
头文件:#include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h>
返回值:成功返回共享内存映射的地址,失败返回NULL - memcpy——把指定内容拷贝到地址空间
void memcpy(拷贝的地址空间,拷贝的内容,拷贝的内容大小)
头文件:#include <string.h>
返回值:成功返回指向void类型的一个地址,失败返回NULL - shmctl——对共享内存进行设置
int shmctl(共享内存的id,int cmd,保存获取得到的共享内存的信息)cmd 含义 IPC_RMID 删除共享内存,此时第三个参数写NULL IPC_STAT 获取共享内存属性 IPC_SET 修改共享内存 头文件:#include <sys/ipc.h> #include <sys/shm.h> 返回值:成功返回值根据cmd的参数决定,失败返回-1
信号量集
-
semget——创建或访问一个已存在的信号集
int semget(键值,信号量集的数量(一般写1),要进行的操作(IPC_CREAT|0666))头文件:#include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h>
返回值:成功返回信号量集的IPC标识符,失败返回-1 -
semctl——对信号量进行操作
int semctl(信号量id,要操作的集合中信号量的编号(从0开始,一般取值为0),cmd,...)cmd 含义 IPC_RMID 立即删除信号集唤醒所有被阻塞的进程 SETVAL 根据指定的信号量编号设定相应的值 GETVAL 根据指定的信号量编号返回相应的值 union semun { int val; /* Value for SETVAL */ struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ unsigned short *array; /* Array for GETALL, SETALL */ struct seminfo *__buf; /* Buffer for IPC_INFO*/ };
头文件:#include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h>
返回值:成功返回值根据cmd的参数决定,失败返回-1 -
semop——对信号量进行P/V操作
int semop(信号量的id,操作对象的首地址,对信号量的操作(封装在了一个结构体里))sops:操作的核心结构体 struct sembuf { short sem_num; // 信号量集的个数,单个信号量设置为0。 short sem_op; // 信号量在本次操作中需要改变的数据:-1-等待操作;1-发送操作。 short sem_flg; // 把此标志设置为SEM_UNDO,操作系统将跟踪这个信号量。 // 如果当前进程退出时没有释放信号量,操作系统将释放信号量,避免资源被死锁。 };
头文件:#include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h>
返回值:成功返回0,失败返回-1
消息队列
- msgget——创建/获取消息队列
int msgget(键值,要进行的操作(IPC_CREAT|0666))
头文件:#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h>
返回值:成功返回消息队列的id,失败返回-1 - msgsend——发送消息到消息队列里
int msgsend(消息队列的id,发送消息的结构体,发送消息的正文大小,一般赋0)
头文件:#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h>
返回值:成功返回0,失败返回-1 - msgrcv——从消息队列里接收指定的消息类型
ssize_t msgrcv(消息队列的id,发送消息的结构体,发送消息的正文大小,消息类型,一般赋0)
头文件:#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h>
返回值:成功返回0,失败返回-1 - msgctl——控制消息队列
int msgctrl(msqid(消息队列id),cmd,buf)cmd 含义 IPC_STAT 读取消息队列的 msgrcv数据结构msqid_ds,并将其存在指buf定的地址中 IPC_SET 设置消息队列的数据结构msqid_ds中的ipc_perm元素值 IPC_RMID 从系统内核中移走消息队列,第三个参数直接给NULL 头文件:#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> 返回值:成功返回0,失败返回-1
线程
线程相关函数
- pthread_self——获取线程ID
pthread_t pthread_self(void)
头文件:#include <pthread.h>
返回值:线程ID(总是成功,不会失败) - pthread_equal——判断两线程是否相等
int pthread_eqtal(线程ID,线程ID);
头文件:#include <pthread.h>
返回值:成功返回非0值,失败返回0 - pthread_create——创建线程
int pthread_create(线程标识符地址,线程属性结构体地址(通常设置为NULL),线程函数入口地址,传给线程函数的参数)
头文件:#include <pthread.h>
返回值:成功返回0,失败返回非0 - pthread_join——线程资源回收(会阻塞)
int pthread_join(被等待的线程号,用来存储线程退出状态的指针地址)
头文件:#include <pthread.h>
返回值:成功返回0,失败返回非0 - pthread_detach——线程分离
int pthread_detach(线程ID)
头文件:#include <ptread.h>
返回值:成功返回0,失败返回非0 - pthread_exit——线程退出
void pthread_exit(存储线程退出状态的指针(一般填NULL))
头文件:#include <pthread.h>
返回值:无 - pthread_cancel——线程取消
int pthread_cancel(线程ID)
头文件:#include <pthread.h>
返回值:成功返回0,失败返回出错编号 - pthread_cleanup——线程清理函数
void pthread_cleanup_pop(决定是否要执行注册函数的关键(非0执行;0不执行))——决定是否使用注册的清理函数
void pthread_cleanup_push(要注册的清理函数,传递给清理函数的参数)——注册清理函数
遵循栈的规则,先注册后执行
头文件:#include <pthread.h>
返回值:无
线程通信
- pthread_kill——给线程发送指定信号
int pthread_kill(线程ID,发送的信号)
头文件:#include <pthread.h>
返回值:成功返回0,失败返回-1
线程的属性
typedef struct
{
int etachstate; //线程的分离状态
int schedpolicy; //线程调度策略
struct sched_param schedparam; //线程的调度参数
int inheritsched; //线程的继承性
int scope; //线程的作用域
size_t guardsize; //线程栈末尾的警戒缓冲区大小
int stackaddr_set; //线程的栈设置
void* stackaddr; //线程栈的位置
size_t stacksize; //线程栈的大小
} pthread_attr_t;
初始化线程属性
pthread_attr_t attr;
int ret = pthread_attr_init(&attr);
if(0!=ret)
{
printf("pthread_attr_init failed...\n");
return 1;
}
printf("线程初始化函数ok...\n");
销毁线程属性
int ret = pthread_attr_init(&attr);
if(0!=ret)
{
printf("pthread_attr_destory failed...\n");
return 0;
}
线程的分离状态
- pthread_attr_setdetachstate——设置线程分离状态
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
attr:已初始化的线程属性
detachstate——分离状态- PTHREAD_CREATE_DETACHED(分离线程)
- PTHREAD_CREATE_JOINABLE(非分离线程)、
头文件:#include <pthread.h>
返回值:成功返回0,失败返回非0
- pthread_attr_getdetachstate——获取线程分离状态
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
attr:已初始化的线程属性
detachstate——分离状态
PTHREAD_CREATE_DETACHED(分离线程)
PTHREAD _CREATE_JOINABLE(非分离线程)
头文件:#include <pthread.h>
返回值:成功返回0,失败返回非0
互斥锁
- pthread_mutex_init——初始化一个互斥锁
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr)
restrict——C语言中的一种类型限定符(Type Qualifiers),用于告诉编译器,对象已经被指针所引用,不能通过除该指针外所有其他直接或间接的方式修改该对象的内容。
mutex——互斥锁地址。类型是 pthread_mutex_t。
attr——设置互斥量的属性,通常可采用默认属性,即可将 attr 设为 NULL。
可以使用宏 PTHREAD_MUTEX_INITIALIZER 静态初始化互斥锁,比如:pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;这种方法等价于使用 NULL 指定的 attr 参数调用 pthread_mutex_init() 来完成动态初始化,不同之处在于 PTHREAD_MUTEX_INITIALIZER 宏不进行错误检查。
头文件:#include <pthread.h>
返回值:成功返回0(成功申请的锁默认是打开的),失败返回非0 - pthread_mutex_destroy——销毁指定的互斥锁
int pthread_mutex_destroy(互斥锁地址)
头文件:#include <pthread.h>
返回值:成功返回0,失败返回非0 - pthread_mutex_lock——对互斥锁上锁,若已上锁则调用者堵塞,直到互斥锁解锁才上锁
int pthread_mutex_lock(互斥锁地址)
头文件:#include <pthread.h>
返回值:成功返回0,失败返回非0
int pthread_mutex_trylock(互斥锁地址)——不会阻塞
若互斥锁未加锁,则上锁,返回0;
若互斥锁已加锁,则函数直接返回失败,即EBUSY - pthread_mutex_unlock——对指定互斥锁解锁
int pthread_mutex_unlock(互斥锁地址)
头文件:#include <pthread.h>
返回值:成功返回0失败返回非0
读写锁
- pthread_rwlock_init——初始化读写锁
int pthread_unlock_init(pthread_rwlock_t *restrict rwlock,const pthread_rwlockattr_t *restrict attr)
rwlock:指向要初始化的读写锁指针。
attr:读写锁的属性指针。如果 attr 为 NULL 则会使用默认的属性初始化读写锁,否则使用指定的 attr 初始化读写锁。
可以使用宏 PTHREAD_RWLOCK_INITIALIZER 静态初始化读写锁,比如:pthread_rwlock_t my_rwlock = PTHREAD_RWLOCK_INITIALIZER;这种方法等价于使用 NULL 指定的 attr 参数调用 pthread_rwlock_init() 来完成动态初始化,不同之处在于PTHREAD_RWLOCK_INITIALIZER 宏不进行错误检查。
头文件:#include <pthread.h>
返回值:成功返回0,失败返回非0 - pthread_rwlock_destroy——销毁一个读写锁
int pthread_rwlock_destroy(读写锁指针)
头文件:#include <pthread.h>
返回值:成功返回0,失败返回非0 - pthread_rwlock_rdlock——读锁定
int pthread_rwlock_rdlock(读写锁指针)
头文件:#include <pthread.h>
返回值:#成功返回0,失败返回非0
int pthread_rwlock_tryrdlock(读写锁指针)
尝试以非阻塞方式在读写锁上获取读锁;若有写者持有或写者堵塞在该读锁,则立即失败返回 - pthread_rwlock_wrlock——读锁定
int pthread_rwlock_wrlock(读写锁指针)
头文件:#include <pthread.h>
返回值:#成功返回0,失败返回非0
int pthread_rwlock_trywrlock(读写锁指针)
尝试以非阻塞方式在读写锁上获取写锁;若有任何读者或写者该锁,则立即失败返回 - pthread_rwlock_unlock——解锁读写锁
int pthread_rwlock_unlock(读写锁指针)
头文件:#include <pthread.h>
返回值:成功返回0,失败返回非0
条件变量
-
pthread_cond_init——初始化一个条件变量
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr)
cond:指向要初始化的条件变量指针。
attr:条件变量属性,通常为默认值,传NULL即可也可以使用静态初始化的方法,初始化条件变量:pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
头文件:#include <pthread.h>
返回值:成功返回0,失败返回非0 -
pthread_cond_destroy——销毁一个条件变量
int pthread_cond_destroy(条件变量指针)
头文件:#include <pthread.h>
返回值:成功返回0,失败返回非0 -
pthread_cond_wait——阻塞等待一个条件变量
int pthread_cond_wait(指向要初始化的条件变量指针,互斥锁)
头文件:#include <pthread.h>
返回值:成功返回0,失败返回非0 -
pthread_cond_timedwait——限时等待一个条件变量
int pthread_cond_wait(条件变量指针,互斥锁,const struct.*restrict abstime)
abstime:绝对时间
头文件:#include <pthread.h>
返回值:成功返回0,失败返回非0abstime补充说明: struct timespec { time_t tv_sec; /* seconds */ // 秒 long tv_nsec; /* nanosecondes*/ // 纳秒 } time_t cur = time(NULL); //获取当前时间。 struct timespec t; //定义timespec 结构体变量t t.tv_sec = cur + 1; // 定时1秒 pthread_cond_timedwait(&cond, &t);
-
pthread_cond_signal——唤醒阻塞在条件变量上的线程
int pthread_cond_signal(条件变量指针)
头文件:#include <pthread.h>
返回值:成功返回0,失败返回非0 -
pthread_cond_broadcast——唤醒全部阻塞在条件变量上的线程
int pthread_cond_broadcast(条件变量指针)
头文件:#include <pthread.h>
返回值:成功返回0,失败返回非0
信号量
-
sem_init——创建一个信号量并初始化它的值,无名信号量在被使用前必须先初始化
int sem_init(信号量的地址,(填0信号量在线程间共享;填非0信号量在进程间共享),信号量的初始值)
头文件:#include <semaphore.h>
返回值:成功返回0,失败返回-1 -
sem_destroy——删除sem标识的信号量
int sem_destroy(信号量地址)
头文件:#include <semaphore.h>
返回值:成功返回0,失败返回-1 -
sem_wait——信号量P操作(减1)(会阻塞)
int sem_wait(信号量地址)
头文件:#include <semaphore.h>
返回值:成功返回0,失败返回-1 -
sem_trywait——信号量P操作(减1)(非阻塞)
int sem_trywait(信号量地址)
头文件:#include <semaphore.h>
返回值:成功返回0,失败返回-1 -
sem_timedwait——限时尝试将信号量的值减1
int sem_timedwait(信号量地址,abs_timeout)
头文件:#include <semaphore.h>
返回值:成功返回0,失败返回-1struct timespec { time_t tv_sec; /* seconds */ // 秒 long tv_nsec; /* nanosecondes*/ // 纳秒 } time_t cur = time(NULL); //获取当前时间。 struct timespec t; //定义timespec 结构体变量t t.tv_sec = cur + 1; // 定时1秒 sem_timedwait(&cond, &t);
-
sem_post——信号量V操作(加1)
int sem_post(信号量的地址)
头文件:#include <semaphore.h>
返回值:成功返回0,失败返回-1 -
sem_getvalue——获取sem标识的信号量的值
int sem_getvalue(信号量地址,保存信号量值的地址)
头文件:#include <semaphore.h>
返回值:成功返回0,失败返回-1
Linux网络编程
socket套接字
网络字节序和主机字节序的转化
头文件:#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint32_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint32_t ntohs(uint16_t netshort);
char buf[4]={192,168,1,2};
int num=*(int*)buf;
int sum=htonl(num);
unsigned char *p=∑
printf("%d %d %d %d\n",\*p,\*(p+1),\*(p+2),\*(p+3));
IP转换
- inet_pton——将点分十进制转换成32位网络大端数据
int inet_pton((IPV4填AF_INET;IPV6填AF_INET6),点分十进制的首地址,32位网络数据的地址)
头文件:#include <arpa/inet.h>
返回值:成功返回1,失败返回0或-1 - inet_ntop——将32位大端的网络数据转换成点分十进制串
const char *inet_ntop(AF_INET,32位大端的网络数地址,存储点分十进制串地址,存储点分制串的数组大小)
头文件:#include <arpa/inet.h>
返回值:成功返回存储点分制串数组的首地址,失败返回NULL
套接字结构体
套接字协议组
#define AF_UNSPEC 0 // 未指定
#define AF_UNIX 1 // 本地套接字
#define AF_INET 2 // IPv4 协议族
#define AF_AX25 3 // AX.25 协议族
#define AF_IPX 4 // IPX 协议族
#define AF_APPLETALK 5 // AppleTalk 协议族
#define AF_NETROM 6 // NET/ROM 协议族
#define AF_BRIDGE 7 // 桥接协议族
#define AF_ATMPVC 8 // ATM PVC 协议族
#define AF_X25 9 // X.25 协议族
#define AF_INET6 10 // IPv6 协议族
套接字类型:
SOCK_STREAM:流套接字,用于实现 TCP 通信。
SOCK_DGRAM:数据报套接字,用于实现 UDP 通信。
SOCK_RAW:原始套接字,用于实现 IP 数据包通信。
传输协议:
1. IPPROTO_TCP:TCP 传输协议,用于实现面向连接的、可靠的、数据无错且无重复的数据传输服务。
2. IPPROTO_UDP:UDP 传输协议,用于实现面向无连接的服务,以独立的数据报形式发送数据,不提供正确性检查,也不保证各数据包的发送和接收顺序。
3. 0表示使用默认的传输协议。例如,当创建一个流套接字时,如果传输协议填 0,则默认使用 TCP 传输协议;当创建一个数据报套接字时,如果传输协议填 0,则默认使用 UDP 传输协议
#include <arpa/inet.h>
通用套接字结构体
struct sockaddr {
sa_family_t sa_family; // 协议族
char sa_data[14]; // 地址信息
};
IPV4 套接字结构体
struct sockaddr_in {
sa_family_t sin_family; // 地址族(Address Family)
in_port_t sin_port; // 端口号
struct in_addr sin_addr; // IP地址
};
struct sockaddr {
sa_family_t sa_family; // 地址族
char sa_data[14]; // 地址信息
};
IPV6 套接字结构体
struct sockaddr_in6 {
sa_family_t sin6_family; // 地址族(Address Family)
in_port_t sin6_port; // 端口号
uint32_t sin6_flowinfo; // 流信息
struct in6_addr sin6_addr; // IPv6地址
uint32_t sin6_scope_id; // Scope ID
};
struct in6_addr {
unsigned char s6_addr[16]; // IPv6地址
};
作为客户端与服务端通信步骤
- 创建套接字:使用 socket 函数创建一个套接字。
- 连接服务器:使用 connect 函数连接到服务器。
- 发送数据:使用 send 函数发送数据到服务器。
- 接收数据:使用 recv 函数接收来自服务器的数据。
- 关闭套接字:使用 close 函数关闭套接字。
作为服务端与客户端通信步骤
- 创建套接字:使用 socket 函数创建一个套接字。
- 绑定地址:使用 bind 函数将套接字绑定到一个地址上。
- 监听连接:使用 listen 函数监听来自客户端的连接请求。
- 接受连接:使用 accept 函数接受来自客户端的连接请求。
- 通信:使用 send 和 recv 函数与客户端进行通信。
- 关闭连接:使用 close 函数关闭与客户端的连接。
套接字函数
- socket——创建一个新的套接字
int socket(套接字协议族,套接字类型,具体使用的协议(通常设置为0表示默认协议))
头文件:#include <sys/socket.h>
返回值:成功返回一个新的套接字描述符,失败返回-1 - connect——连接服务器
int connect(套接字描述符,服务器的套接字地址,套接字结构体长度)
头文件:#include <sys/socket.h>
返回值:成功返回0,失败返回-1 - bind——给套接字绑定固定的端口和ip
int bind(套接字,ipv4套接字结构体地址,结构体长度)
头文件:#include <sys/socket.h>
返回值:成功返回0,失败返回-1 - listen——监听
int listen(套接字,已完成队列数之和与未完成队列数之和的最大值(一般填128))
头文件:#include <sys/socket.h>
返回值:成功返回0,失败返回-1 - accept——从已完成连接队列提取新的连接
int accept(套接字,ipv4套接字结构体地址,ipv4套接字结构体大小的地址)
头文件:#include <sys/scoket.h>
返回值:成功返回新的已连接套接字的文件描述符,失败返回-1
多路IO复用
端口复用
int opt = 1;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
select
#include <sys/select.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/time.h>
int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);
1. nfds 是指定待测试的描述字个数,它的值是待测试的最大描述字加1。
2. readfds、writefds 和 exceptfds 分别指向可读、可写和异常等事件对应的描述符集合。如果对某一个条件不感兴趣,就可以把它设为空指针。
3. timeout 参数用于设置 select 函数的超时时间,即告诉内核 select 等待多长时间之后就放弃等待。这个参数有三种可能:永远等待下去(将该参数设置为空指针 NULL)、等待一段固定时间(在有一个描述字准备好 I/O 时返回,但是不超过由该参数所指向的 timeval 结构中指定的秒数和微秒数)、根本不等待(检查描述字后立即返回,这称为轮询)。
返回值:返回变化的描述字个数,如果超时则返回 0,如果出错则返回 -1。
struct timeval {
long tv_sec; //秒
long tv_usec; //微秒
};
使用 select 时,需要配合一些宏来操作文件描述符集合。这些宏包括:
void FD_ZERO(fd_set *fdset); //清空集合
void FD_SET(int fd, fd_set *fdset); //将一个给定的文件描述符加入集合之中
void FD_CLR(int fd, fd_set *fdset); //将一个给定的文件描述符从集合中删除
int FD_ISSET(int fd, fd_set *fdset); //检查集合中指定的文件描述符是否可以读写,返回1表示有变化
poll
#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
1. fds 是一个指向 pollfd 结构体数组的指针,该结构体用于指定要监视的文件描述符及其所需的事件。
2. nfds 是 fds 数组中的元素数量。
3. timeout 指定等待时间(以毫秒为单位)。如果设置为 -1,则 poll 将无限期等待;如果设置为 0,则立即返回。
struct pollfd {
int fd; /* 文件描述符 fd 是要监视的文件描述符 */
short events; /* 请求的事件 events 是要监视的事件掩码,可以是以下常量的按位或组合:POLLIN(有数据可读)、POLLOUT(写数据不会阻塞)和 POLLERR(发生错误) */
short revents; /* 返回的事件 revents 是返回的事件掩码,它指示哪些请求的事件实际发生 */
};
返回值:成功返回就绪的文件描述符数量,如果超时则返回 0,如果出错则返回 -1。
epoll
1. epoll_create
#include <sys/epoll.h>
int epoll_create(int size);
size 是要监视的文件描述符数量。且最小为 1
返回值:成功返回新创建的epoll实例的文件描述符,失败返回-1
2. epoll_ctl
#include <sys/epoll.h>
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
epfd 是要操作的epoll实例文件描述符
op 是操作:
EPOLL_CTL_ADD:注册新的 fd 到 epfd 中;
EPOLL_CTL_MOD:修改已经注册的 fd 的监听事件;
EPOLL_CTL_DEL:从 epfd 中删除一个 fd;
fd 是需要监听的文件描述符。
event 是一个指向 epoll_event 结构体的指针,用来告诉内核需要监听什么事件。
struct epoll_event
{
__uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
events 成员变量是一个位掩码,用来指定感兴趣的事件类型。它可以是以下几个宏的集合:
EPOLLIN:表示对应的文件描述符可以读(包括对端 SOCKET 正常关闭)。
EPOLLOUT:表示对应的文件描述符可以写。
EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来)。
EPOLLERR:表示对应的文件描述符发生错误。
EPOLLHUP:表示对应的文件描述符被挂断。
EPOLLET:将 EPOLL 设为边缘触发 (Edge Triggered) 模式,这是相对于水平触发 (Level Triggered) 来说的。
EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个 socket 的话,需要再次把这个 socket 加入到 EPOLL 队列里。
data 成员变量是一个联合体,用来存储用户数据。它可以是一个指针、一个文件描述符或者其他类型的数据。
typedef union epoll_data
{
void *ptr;
int fd;
__uint32_t u32;
__uint64_t u64;
} epoll_data_t;
返回值:成功返回0,失败返回-1
3. epoll_wait
#include <sys/epoll.h>
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
epfd 是 epoll_create 的返回值。
events 是一个指向 epoll_event 结构体数组的指针,用于从内核获取事件集合。
maxevents 表示本次可以返回的最大事件数目,这个值不能大于创建 epoll_create() 时的 size。
timeout 是超时时间(毫秒,0 会立即返回,-1 将不确定,也有说法说是永久阻塞)。
返回值:成功返回发生事件个数,超时返回0,失败返回-1
数据库
安装:
- 服务器的安装:sudo apt-get install mysql-server
- 客户端的安装:sudo apt-get install mysql-client
- 开发包的安装:sudo apt-get install libmysqlclient-dev
安装结果检测:netstat -tap | grep mysql
修改密码:
- sudo mysql -uroot 回车直接登录
- 修改密码:alter user 'root'@'localhost' identified with mysql_native_password by '这里是密码';
- 执行:flush privileges;使密码生效,然后使用root用户登录。
- 登录 mysql -u root -p
启动:service mysql start
关闭:service mysql stop
重启:service mysqld restart
如何解决下面问题:mysql> SHOW DATABASES;
ERROR 1449 (HY000): The user specified as a definer ('mysql.infoschema'@'localhost') does not exist
1. CREATE USER 'mysql.infoschema'@'%' IDENTIFIED BY '密码';————创建一个名为 mysql.infoschema 的用户,该用户可以从任何主机连接到 MySQL 服务器,密码为 '密码'。
2. GRANT ALL PRIVILEGES ON *.* TO 'mysql.infoschema'@'%';————授予 mysql.infoschema 用户对所有数据库和表的所有权限。
3. FLUSH PRIVILEGES;————刷新权限,使更改立即生效。
关键字
关键词 | 含义 |
---|---|
database | 数据库 |
table | 表格 |
column | 列 |
select | 选中 |
show | 显示 |
updata | 更新 |
drop delete | 删除 |
change | 更改 |
from | 来自 |
整型
标识符 | 大小 |
---|---|
TINYINT | 1字节 |
SMALLINT | 2字节 |
INT | 4字节 |
MEDIUMINT | 3字节 |
BIGINT | 8字节 |
浮点型
标识符 | 大小 |
---|---|
FLOAT | 4字节 |
DOUBLE | 8字节 |
字符型
标识符 | 大小 |
---|---|
CHAR | 单字符 |
CHAR(N) | N代表数字 char a[n]; |
VCHAR(N) | 用多少开辟多少 |
TINYTEXT | 存储文本--字符串 |
时间类型
标识符 | 大小 | 格式 |
---|---|---|
DATE | 4字节 | YYYY-MM-DD (零值:0000:00:00) |
TIME | 3字节 | HH:MM:SS (零值: 0000) |
YEAR | 1 | YYYY (零值: 0000) |
DATETIME | 8 | YYYY-MM-DD HH:MM:SS(零值:0000-00-00 00:00:00) |
SQL语法的增删改查排序
显示
- 显示目前所有的数据库
show databases; //显示目前所有的数据库(文件夹) - 显示数据库中的表
show tables from xxx(某个数据的名字); //显示某个数据库里面的所有的表
show tables; //显示你正在使用的数据库的表 - 选中数据库 // 必须已经选中某个数据库使用 -- use xxx(数据库名字)
use xxx(数据库的名字) //选中某个数据库 - 显示表里面的列信息(表头!)
show columns from xxx(某个表) //已经有选中的数据库了 //不然你要指定数据
show columns from xxx(某个表)from xxx(某个数据库) //显示任意数据库里面任意表的表头信息
查找
- select * from xxx表 //显示表里面的所有内容
- select name,age,new_sex from xxx表 //我仅仅想显示 这三列
- select name,age,new_sex from new_my_pet where age < 18 AND new_sex = 'w'; //显示 三列信息 且 性别是女 且 年龄小于18
增加
创建数据库
创建表必须加表头信息
增加数据信息
- 创建一个数据库
create database [db_name]; //创建一个名字叫做 db_name的数据库 - 创建表 ---- 必须加表头信息
create table [table_name](name CHAR(20),id INT,sex CHAR,aihao CHAR(20),birth DATE,death DATE) - 添加表里面的信息--- insert --插入
insert into my_pet values('zhangsan',1,'m','play game','1990-08-01',NULL); //插入的信息要跟表头一一对应
修改
- 改表的名字
alter table tbl_name(之前的表名) rename new_tbl(新的表名)
alter table my_pet rename new_pet; //把 my_pet 改成 new_pet 名字 - 增加一列
alter table new_pet add age TINYINT; //给new_pet 增加一列 age 类型是 TINYINT - 删除列
alter table new_pet drop age; //把 new_pet 表里 的age列删除 - 改数据的信息(update)
update new_pet set death = '2021-07-26' where name = 'zhangsan' //把 'zhangsan' 的 death设置为 '2021-07-26'
删除
delete drop
- 删除一个数据库
drop database [数据库的名字] - 删除一个表格
drop table [表的名字] - 如何删除列
alter table new_pet drop age; //把 new_pet 表里 的age列删除 - 删除一行数据
delete from new_pet where name ='zhaosi';
排序
对于某个关键的数据进行排序:
ASC——升序
DESC——降序
排序有个关键字 :ORDER - order
select * from new_pet order by birth; //默认就是 ASC 升序
select * from new_pet order by birth DESC; //就是降序
数据库函数
1. 链接数据库
#include<mysql/mysql.h>
MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long client_flag)
mysql:他是Mysql但是他必须是使用MYSQL *mysql_init(MYSQL *mysql)函数初始化之后的
host:你的主机ip如果是本地就写 "localhost"
user:数据的用户名
passwd:数据库的密码
db:你要操作的数据库
port:端口号,本地就写 0
unix_socket:远程套接字,本地NULL
client_flag:通常是 0
函数返回值: 功返回与第一个参数相同的值,失败NULL
2. 执行mysql支持的指令
#include<mysql/mysql.h>
int mysql_query(MYSQL *mysql, const char *query)
mysql:就是链接函数的返回值
query:你要执行的mysql的指令
返回值:成功返回 0 失败 1
3. 就是把查询到的数据库里的信息保存的本地
#include<mysql/mysql.h>
MYSQL_RES *mysql_store_result(MYSQL *mysql)
mysql:就是链接函数的返回值
返回值:成功返回指向MYSQL_RES指针,失败NULL
4. 从获取得到的结果集里获取行数
#include<mysql/mysql.h>
my_ulonglong mysql_num_rows(MYSQL_RES *result)
result:获取结果集合函数的返回值 mysql_store_result
返回值:成功返回行数
5. 从获取得到的结果集里获取列数
#include<mysql/mysql.h>
unsigned int mysql_num_fields(MYSQL_RES* res)
result:获取结果集合函数的返回值 mysql_store_result
返回值: 成功返回列数
6. 检索结果集合的下一行
#include<mysql/mysql.h>
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)
函数参数:result:获取结果集合函数的返回值 mysql_store_result
返回值:成功返回获取得到的这一行的信息,其实他就是一个数组
7. 释放你查询的结果集
#include<mysql/mysql.h>
void mysql_free_result(MYSQL_RES *result)
result:获取结果集合函数的返回值 mysql_store_result
返回值:无
ps:你在第二次查询的时候必须要先把第一次你查询的结果集给释放掉,这样才不会出现查询有错误的问题。
8. 关闭数据库
#include<mysql/mysql.h>
void mysql_close(MYSQL *mysql)
mysql:链接数据库函数的返回值
返回值:无
9. 打印出错的信息
#include<mysql/mysql.h>
const char* mysql_error(MYSQL* mysql)
mysql:链接数据库函数的返回值
返回值:成功返回错误的信息,失败NULL
标签:返回,头文件,int,pthread,系统,笔记,Linux,返回值,include
From: https://www.cnblogs.com/Ron01/p/17513142.html