首页 > 系统相关 >Linux系统笔记

Linux系统笔记

时间:2023-08-02 23:33:43浏览次数:34  
标签:返回 头文件 int pthread 系统 笔记 Linux 返回值 include

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:查看文件的详细信息

  1. 第一位代表文件类型:
    -:普通文件
    l:链接文件————快捷方式
    d:目录
    b:块设备————U盘 硬盘
    p:管道————进程直接的通信方式
    c:字符设备
    s:套接字————进程之间进行通信的方法
  2. 第2-4位:代表文件的拥有者对文件拥有的权限
    r:可读————4
    w:可写————2
    x:可执行——1
    如果一个权限没有就使用 - 表示
    创建文件时系统不会默认给最高权限,命令umask,0002:0:代表八进制;0:第一个用户;0:第二个用户;2:代表第三个用户
  3. 第5-7位:代表同组用户对文件拥有的权限
  4. 第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的四种模式:

  1. 命令行模式
    1. 复制:(n)yy n表示从光标当前所在行开始往下复制多少行
    2. 粘贴:p
    3. 删除:(n)dd n表示从光标当前所在行开始往下删除多少行
    4. 撤销:u
    5. gg:从光标所在位置跳转到代码的开头
    6. G:从光标所在位置跳转到代码的结尾
    7. gg=G:代码自动对齐
  2. 插入模式
    1. 在命令行模式按i进入插入模式
  3. 底行模式
    1. 进入底行模式:shift + :
    2. w:保存不退出
    3. w!:强制保存
    4. q:不保存退出,如果文件内容有改动会无法退出
    5. q!:强制退出不保存
    6. wq:保存并退出
    7. x:如果修改了就保存退出,如果没有就直接退出
    8. /关键字:查找关键字,如果有就高亮显示(前提是配置了高亮显示)
    9. noh:去除高亮
    10. %s/原字符串/替换的字符串/g:字符串替换
  4. 可视模式
    1. 命令行模式下按v进入可视模式
    2. d:删除
    3. y:复制
    4. x:剪切

vim的配置文件位置:/etc/vim/vimrc
sudo gedit /etc/vim/vimrc

编译工具

编译工具:gcc:把代码翻译成计算机能够识别的二进制文件
一个.c文件从编写到执行的四个过程

  1. 编译预处理
    1. gcc -E xxx.c -o xxx.i:处理宏定义,就是以#开头的
  2. 编译
    1. gcc -S xxx.i -o xxx.s:进一步把编译预处理后的文件做语法检查
  3. 汇编
    1. as xxx.s -o xxx.o:将汇编代码翻译成所对应的机器指令,一条汇编代码对应一条机器指令
  4. 链接
    1. 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的使用

  1. gdb 文件名:进入gbd
  2. r:开始运行
  3. l:查看源码信息
  4. break/b:设置断点
  5. b:行号/函数名
  6. info b:查看断点信息
  7. printf/p:查看变量当前的值
  8. n:单步运行:遇到函数不会跳到函数内部,而是直接拿到函数的运行结果
  9. s:单步运行:遇到函数,跳到函数的内部去运行,在函数内运行完才结束
  10. 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无缓存
每运行一个进程,系统默认打开三个流:

  1. stdin——0:有缓存——对应键盘
  2. stdout——1:有缓存——对应显示屏
  3. stderr——2:无缓存——对应显示屏

缓存区输出条件:

  1. 遇到\n
  2. 程序结束
  3. fflush()
  4. 全缓存 行缓存,行缓存大小1024

标准IO操作函数

  1. fopen——打开文件
    FILE fopen(文件路径,打开模式)
    FILE
    名称=fopen(文件路径,打开模式)
    模式:
    1. “r”:只读,文件不存在,打开失败
    2. “w”:只写,文件不存在,创建打开,存在,清空写
    3. “a”:只写,文件不存在,创建打开,存在,追加写
    4. “r+”:读写,文件不存在,打开失败
    5. “w+”:读写,文件不存在,创建打开,存在,清空写
    6. “a+”:读写,文件不存在,创建打开,存在,追加写
      函数返回值:成功返回名称,失=失败返回NULL
  2. perror——打印离他最近的函数执行失败的原因
    perror(const char *s)
    s:错误标题
  3. fclose——关闭文件
    int fclose(fopen的名称)
    返回值:关闭成功返回0,失败返回-1
  4. fputc——单字符写入
    int fputc(char类型单字符,fopen的名称)
    返回值:返回写入的字符,失败返回-1
  5. fgetc——单字符读取
    int fgetc(fopen的名称)
    返回值:成功返回取得的单个字符,失败返回-1
  6. fputs——字符串写入
    char *fputs(要写入的字符串的首地址,fopen的名称)
    返回值:成功返回写入的字节大小,失败返回-1
  7. fgets——字符串的读取
    char *fgets(读取到的内容存放的地址,读取多大,fopen的名称)
    返回值:成功返回获取的字符串,失败返回NULL
  8. feof——判断文件是否到达文件末尾
    feof(fp):到结尾返回非0值,否则返回0
    不会造成光标偏移
  9. fwrite——块写
    fwrite(写入到文件中的首地址,一次写入多大字节,写入几次,fopen名称)
    返回值:成功返回写入字节大小,失败返回-1
  10. fread——块读
    fread(读取到的内容存放的首地址,一次都多大字节,读取几次,fopen名称)
    返回值:成功返回读取字节大小,失败返回-1
  11. rewind——使光标回到文件开头
    rewind(fopen的名称)
    返回值:无
  12. fseek——光标偏移函数
    fseek(fp,偏移量,偏移量的起始位置)
    偏移量:+表示往文件末尾便宜,-表示往文件起始位置偏移
    起始位置:0——SEEK_SET:文件开头,1——SEEK_CUR:当前位置,2——SEEK_END:文件末尾
    返回值:成功返回0,失败返回-1
  13. ftell——计算文件当前位置到文件开头的偏移量
    tell()
  14. fprintf——格式化写入
    fprintf(fopen名称,"%d",a);
    返回值:成功返回0,失败返回-1
  15. fscanf——格式化读取
    fscanf(fopen名称,"%d",&a);
    返回值:成功返回0,失败返回-1
    fprintf和fscanf格式必须一至才能准确读取
  16. sprintf——格式化复制
    int sprintf(要复制内容的保存位置,要操作的格式,要操作的变量)
    返回值:成功返回0,失败返回-1
  17. atoi——把字符串转换成整型
    int atoi(要转换的变量)
    返回值:成功返回转换之后的类型,失败返回-1

文件IO操作函数

  1. 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

  2. close——关闭文件
    int close(文件名)
    头文件:#include <unistd.h>
    返回值:成功返回0,失败返回-1

  3. read——从文件里读取内容
    ssize_t read(文件名,要读入的缓冲区(提前申请好),读取的大小)
    头文件:#include <unistd.h>
    返回值:成功返回读取到的字节数,失败返回-1

  4. write——向文件里写入内容
    ssize_t write(文件名,写入的空间(提前申请好),写入的内容大小)
    头文件:#include <unistd.h>
    返回值:成功返回写入的字节数,失败-1

  5. lseek——移动光标位置
    off_t lseek(文件名,偏移量,偏移量的起始位置)
    头文件:#include <sys/types.h>/#include <unistd.h>
    返回值:成功返回偏移量的位置,失败返回-1

时间编程

和时间有关的指令

  1. date——显示当前时间
    date -R——以字符串的形式显示
    date -u——世界标准时间
  2. 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>

  1. time——获取当前的日历时间
    time_t time(一般填NULL)
    返回值:成功返回当前日历时间,失败返回-1
  2. gmtime——获取标准时间(格林威治时间)
    struct tm *gmtime(待转化的日历时间)
    返回值:成功返回世界标准时间,失败返回NULL
  3. locatime——获取本地时间
    struct tm *localtime(待转化的日历时间)
    返回值;成功返回本地时间,失败返回NULL
  4. asctime——以字符串的形式去获取时间
    char *asctime(获取本地/标准时间函数的返回值)
    返回值:成功返回字符串显示的时间,失败返回NULL
  5. ctime——直接把日历转换成本地时间
    char *ctime(待转化的日历时间)
    返回值:成功返回本地时间,失败返回NULL
  6. 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; /* 创建时间 */
};

获取文件属性的函数

  1. stat——获取文件的属性
    int stat(文件,文件属性的核心结构体)
    头文件:#include <sys/types.h>/#include <sys/stat.h>/#include <unistd.h>
    返回值:成功返回0,失败返回-1
  2. fstat——获取文件的属性
    int fstat(文件描述符,文件属性的核心结构体)
    头文件:#include <sys/types.h>/#include <sys/stat.h>/#include <unistd.h>
    返回值:成功返回0,失败返回-1
    stat只需要提供一个文件路径,fstat需要使用open函数打开文件,然后用open返回的文件描述符来获取文件的属性
  3. 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:文件是否存在

目录操作

  1. mkdir——创建目录
    int mkdir(文件路径,权限(如:0777权限这里要注意给的权限里要包含x执行权限))
    头文件:#include <sys/stat.h>/#include <sys/types.h>
    返回值:成功返回0,失败返回-1
  2. rmdir==rm——删除目录
    int rkdir(文件路径)
    头文件:#include <unistd.h>
    返回值:成功返回0,失败返回-1
  3. getcwd==pwd——显示当前绝对路径
    char *getcwd(保存当前目录的缓存区,缓存区大小(最大255字节))
    头文件:#include <unistd.h>
    返回值:成功返回当前路径,失败返回NULL
  4. chdir==cd——切换路径
    int chdir(目标路径)
    头文件:#include <unistd.h>
    返回值:成功返回0,失败返回-1
  5. chmod——更改权限
    int chmod(文件路径,权限)
    头文件:#include <sys/types.h>/#include <sys/stat.h>
    返回值:成功返回0,失败返回-1
  6. 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.       未知类型
  1. opendir——打开指定的目录
    DIR *opendir(要打开的目录名)
    头文件:#include <sys/types.h>/#include <dirent.h>
    返回值:成功返回一个指向DIR的指针,失败返回NULL
  2. closedir——关闭打开的目录
    int closedir(要关闭的目录)
    头文件:#include <sys/types.h>/#include <dirent.h>
    返回值:成功返回0,失败返回-1
  3. dirent——读取目录里的内容
    struct dirent *readdir(opendir函数的返回值)
    返回值:成功返回指向struct dirent指针,失败返回NULL
  4. strstr——在字符串中查找特定字符串第一次出现的位置
    char *strstr(源字符串,特定字符串)
    头文件:#include <string.h>
    返回值:成功返回查找到的指向字符串的指针,失败返回NULL
  5. rewinddir——将目录的目录流拉到开头
    void rewinddir(opendir的返回值)
    头文件:#include <sys/types.h>/#include <dirent.h>
    返回值:无
  6. seekdir——把目录流移动到指定位置
    void seekdir(opendir函数的返回值,要移动的位置)
    头文件:#include <dirent.h>
    返回值:无
  7. telldir——获取当前目录流的位置
    off_t tellir(opendir函数的返回值)
    头文件:#include <dirent.h>
    返回值:成功返回目录流的下一个位置,失败返回-1

进程初步

进程即使系统运行的最小单位
进程是程序的一次执行过程,他是一个活的,他和代码时刻都消耗计算机的资源

进程的特性

  1. 独立性:每一个进程的空间都是独立的,每运行一个进程系统都会分配4G的虚拟内存空间
  2. 并发性:一次可以运行多个进程,各自完成不同的任务
  3. 异步性:由于进程间的相互制约,是进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推进
  4. 动态性:进程的实质是程序的一次执行过程,进程是动态产生,动态消亡的

进程的三态

  1. 就绪态:进程已具备执行的一切条件,正等待分配CPU的处理时间片
  2. 等待态:进程正在等待某些事件,当前不能分配时间片,进程不能使用CPU,若等待事件发生(等待的资源分配到)则可将其唤醒,变成就绪态
  3. 执行态:该进程正在运行,即进程正在占用CPU,在任何时候都只有一个进程

如何区分管理进程

PID:相当于进程的身份证号 取值范围32位是32767,64位为2^22,1-300已经被系统占用

特殊进程

  1. 0号进程:引导进程,引导内核的一个进程
  2. 1号进程:系统起来之后运行的第一个进程,这里也叫init进程
  3. 僵尸进程:已经不再给系统做任何贡献,但是还保留着系统的资源,对系统的危害很大,因为系统的资源是有限的
  4. 孤儿进程:父进程先于子进程退出,此时子进程会被init进程收养,init进程给他收尸

进程相关的命令

  1. ps -ef:查看进程的状态

    标志 描述
    UID 用户名
    PID 子进程的ID
    PPID 父进程的ID
    TTY 进程的状态
    CMD 命令名称
    %CPU CPU使用率
    %MEN 内存使用率
    STAT 进程运行的状态
    START 命令启动的时间
    TIME 进程的总执行时间
    VSZ 进程确保的虚拟内存大小
    RSS 实际使用的内存量
  2. top:可以动态的查看进程的状态

  3. ps -aux:显示进程的详细信息

    stat 描述
    S 睡眠
    R 运行(执行或即将运行状态)
    D 不可中断的睡眠(等待),通常等待输入回输出完成
    T 停止,通常是被shell或调试器控制停止
    N 低优先级任务
    Z 僵尸进程
    X 死进程
    s 进程是会话期首进程
    + 后台进程,和用户交互的任务
    | :进程是多线程的
    < :高优先级任务

父进程和子进程

父进程:创建子进程的进程
子进程:被父进程创建的进程
可以通过ctrl+c或者kill -9 pid来杀死一个进程

进程的操作函数

  1. getpid——获取自己的PID
    pid_t getpid(void)
    头文件:#include <sys/types.h>/#include <unistd.h>
    返回值:成功返回自己的PID,失败返回-1
  2. getppid——获取父进程的PID
    pid_t getppid(void)
    头文件:#include <sys/types.h>/#include <unistd.h>
    返回值:成功返回父进程的PID,失败返回-1
  3. fork——创建子进程
    pid_t fork(void)
    头文件:#include <unistd.h>/#include <sys/types.h>
    返回值:在父进程中返回子进程的PID,在子进程中返回0,失败返回-1
    ps:一旦创建成功,那么子进程和父进程就同时运行,但互不干扰,子进程会复制父进程的资源。然后他们各自使用各自的空间变量,他们的运行顺序不确定
  4. vfork——创建子进程
    pid_t vfork(void)
    头文件:#include <unistd.h>/#include <sys/types.h>
    返回值:在父进程中成功返回子进程的PID,在子进程中返回的PID是0,失败返回-1
    ps:一但子进程创建成功,那么一定是先运行子进程,并且是子进程结束了,父进程才会得到运行,也就是说,子进程会阻塞父进程,资源是共享的
    子进程退出的时候一定要使用exit()
  5. wait——等待子进程退出做清理工作
    pid_wait(一般填写NULL)
    头文件:#include <sys/types.h>/#include <sys/wait.h>
    返回值:成功返回结束的那个子进程的PID,失败返回-1
  6. waitpid——等待清理你指定的那个子进程
    pid_t waitpid(要清理的子进程PID,一般写NULL,0(阻塞父进程,同wait)/WNOHANG(若由pid指定的子进程不立即可用,则waitpid不阻塞,此时返回0))
    头文件:#include <sys/types.h>/#include <sys/wait.h>
    返回值:成功返回结束的那个子进程的PID,失败返回-1
  7. _exit——进程正常退出的标准
    void_exit(一般写0即可)
    头文件:#include <stdlib.h>
    返回值:无
    _exit(0)与exit(0)的区别:exit在结束进程时回去清理缓冲区里的内容,然后结束进程;_exit(0)在结束时不会清理缓冲区里的内容,会直接把进程结束掉。一般都是使用exit(0)

exec函数族:这些函数的功能都是实现在一个进程里去执行另一个进程的功能,但是他会覆盖原来的那个进程
exec 是一个函数族,它包括了多个不同的函数,如 execl、execv、execle、execve、execlp、execvp

  1. execl——在一个进程里去执行其他进程
    int execl(要执行这个进程的文件路径(最好写绝对路径),执行这个进程所需要的指令,最后一个参数必须使用NULL)
    头文件:#include <unistd.h>
    返回值:成功返回0,失败返回-1
  2. execlp——在一个进程里去执行其他进程
    int execlp(要执行这个进程的文件路径(系统会默认去环境变量查找,如果找不到就去当前目录找,找不到就报错),执行这个进程所需要的指令,最后一个参数必须使用NULL)
    头文件:#include <unistd.h>
    返回值:成功返回0,失败返回-1

信号以及管道

信号

进程之间为什么要进行通信:

  1. 数据传输
  2. 时间控制
  3. 资源共享

进程通信的方法:

  1. 信号:软中断模拟机制:类似于通知
  2. 管道:进程间直接通信的最简单的方法:可以进行数据传输,具有单向导通性以及阻塞
  3. 共享内存:多个进程共享一块数据可以随时读取以及更改
  4. 消息队列:进程间通信最合理的方法之一:最符合通信思想,单纯收发数据
  5. 信号量集:用来解决进程间资源抢占问题
  6. 套接字:网络中进程通信方法

信号通信

信号通信就是给进程发送一个进程

linux信号分为两部分:

  1. 1-31时unix信号:他是非实时信号:非实时信号没有排队机制,后来信号会打断正在执行的信号,后来的信号执行完后再跳转到原来的信号继续执行
  2. 34-64是自己拓展的实时信号:实时信号谁先来的先处理谁

重要的信号:

  1. 2信号:Ctrl + c
  2. 3信号:Ctrl + \
  3. 9信号:杀死一个进程
  4. 19信号:暂停信号
  5. 18信号:继续信号
  6. 17信号:专门用于父子进程,
    产生条件:
    1. 子进程结束
    2. 子进程遇到19信号,暂停
    3. 子进程从暂停状态回复,遇到18信号
  7. 14信号:闹钟信号

信号操作函数:

  1. signal——捕获指定信号
    sighandler(要捕获的信号,对此信号的处理方式(1.SIG_IGN忽略处理SIGKILL和SIGSTOP信号不能忽略;2.SIG_DFL默认处理,即交给内核,大部分都是杀死进程;3.自己封装函数来处理函数原型typedef void(*sighander_t)(int)))
    头文件啊:#include <signal.h>
    返回值:成功返回,失败返回SIG_ERR

  2. kill——向执行进程发送指定信号
    int kill(进程,信号)
    头文件:#include <sys/types.h>/#include <signal.h>
    返回值:成功返回0,失败返回-1

  3. raise——给本进程发送信号
    int raise(信号)
    头文件:#include <sys/types.h>/#include <signal.h>
    返回值:成功返回0,失败返回-1

  4. alarm——设置时间值,到达时间产生SIGALRM——14信号,不捕捉的时候默认终止进程
    unsigned int alarm(设置的产生闹钟信号的时间)
    头文件:#include <unistd.h>
    返回值:如果调用alarm()之前,进程已经设置了闹钟时间,成功返回剩余闹钟时间,失败返回0

  5. pause——阻塞当前进程,直到捕捉到一个信号
    int pause(void)
    头文件:#include <unistd.h>
    返回值:成功返回0,失败返回-1

  6. glob——在指定的路径下查找指定的文件
    int glob(要查找的路径,一般写0,NULL,找到结果保存的位置(结构体))
    结构体:

    typedef struct
    {
       __size_t gl_pathc;/*指定文件匹配的数量*/
       char **gl_pathv;/*指定匹配文件的文件名*/
    } glob_t;
    

    头文件:#include <glob.h>
    返回值:成功返回0,失败返回-1

管道

进程间通信的方法之一,也是最简单的通信方法

无名管道

在创建时没有名字,专用于父子进程之间

  1. pipe——创建无名管道
    int pipe(管道的两端:pipefd[2](fd[0]读 fd[1]写))
    头文件:#include <unistd.h>
    返回值:成功返回0,失败返回-1
    ps:一旦创建成功就处于打开状态

有名管道

在创建时有名字,用于任意进程之间

  1. mkfifo——创建有名管道
    int mkfifo(管道名(带路径),文件权限)
    头文件:#include <sys/stat.h>/#include <sys/types.h>
    返回值:成功返回0,失败返回-1
    ps:创建成功后使用时必须先打开
  2. unlink——删除管道
    int unlink(管道名(带路径))
    头文件:#include <unistd.h>
    返回值:成功返回0,失败返回-1

共享内存&消息队列&信号量集

共享内存

终端指令:
ipcs -m 查看共享内存
ipcs -q 查看消息队列
ipcs -s 查看信号量集

ipcrm -m xxxid号 删除指定的共享内存
ipcrm -q xxxid号 删除指定的消息队列
ipcrm -s xxxid号 删除指定的信号量

共享内存的方法

  1. 先创建一个键值
  2. 创建/获取一个共享内存
  3. 把共享内存映射到自己的进程里
  4. 对这个共享内存进行读写操作
  5. 解除映射
  6. 删除共享内存

函数:

  1. ftok——创建键值
    key_t ftok(指定的文件,子序列号(取值范围0-255))
    头文件:#include <sys/types.h>/#include <sys/ipc.h>
    返回值:成功返回创建的键值,失败返回-1
  2. shmget——创建/获取共享内存的id
    int shmget(键值,共享内存的大小,操作(IPC_creat|066))
    头文件:#include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h>
    返回值:成功返回共享内存的id,失败返回-1
  3. shmat——映射共享内存到自己的进程里
    void *shmat(共享内存的id,共享内存的资质映射的位置(NULL:系统自动分配,默认0:可读可写))
    头文件:#include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h>
    返回值:成功返回共享内存映射的地址,失败返回NULL
  4. memcpy——把指定内容拷贝到地址空间
    void memcpy(拷贝的地址空间,拷贝的内容,拷贝的内容大小)
    头文件:#include <string.h>
    返回值:成功返回指向void类型的一个地址,失败返回NULL
  5. shmctl——对共享内存进行设置
    int shmctl(共享内存的id,int cmd,保存获取得到的共享内存的信息)
    cmd 含义
    IPC_RMID 删除共享内存,此时第三个参数写NULL
    IPC_STAT 获取共享内存属性
    IPC_SET 修改共享内存
    头文件:#include <sys/ipc.h> #include <sys/shm.h>
    返回值:成功返回值根据cmd的参数决定,失败返回-1

信号量集

  1. semget——创建或访问一个已存在的信号集
    int semget(键值,信号量集的数量(一般写1),要进行的操作(IPC_CREAT|0666))

    头文件:#include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h>
    返回值:成功返回信号量集的IPC标识符,失败返回-1

  2. 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

  3. 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

消息队列

  1. msgget——创建/获取消息队列
    int msgget(键值,要进行的操作(IPC_CREAT|0666))
    头文件:#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h>
    返回值:成功返回消息队列的id,失败返回-1
  2. msgsend——发送消息到消息队列里
    int msgsend(消息队列的id,发送消息的结构体,发送消息的正文大小,一般赋0)
    头文件:#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h>
    返回值:成功返回0,失败返回-1
  3. msgrcv——从消息队列里接收指定的消息类型
    ssize_t msgrcv(消息队列的id,发送消息的结构体,发送消息的正文大小,消息类型,一般赋0)
    头文件:#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h>
    返回值:成功返回0,失败返回-1
  4. 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

线程

线程相关函数

  1. pthread_self——获取线程ID
    pthread_t pthread_self(void)
    头文件:#include <pthread.h>
    返回值:线程ID(总是成功,不会失败)
  2. pthread_equal——判断两线程是否相等
    int pthread_eqtal(线程ID,线程ID);
    头文件:#include <pthread.h>
    返回值:成功返回非0值,失败返回0
  3. pthread_create——创建线程
    int pthread_create(线程标识符地址,线程属性结构体地址(通常设置为NULL),线程函数入口地址,传给线程函数的参数)
    头文件:#include <pthread.h>
    返回值:成功返回0,失败返回非0
  4. pthread_join——线程资源回收(会阻塞)
    int pthread_join(被等待的线程号,用来存储线程退出状态的指针地址)
    头文件:#include <pthread.h>
    返回值:成功返回0,失败返回非0
  5. pthread_detach——线程分离
    int pthread_detach(线程ID)
    头文件:#include <ptread.h>
    返回值:成功返回0,失败返回非0
  6. pthread_exit——线程退出
    void pthread_exit(存储线程退出状态的指针(一般填NULL))
    头文件:#include <pthread.h>
    返回值:无
  7. pthread_cancel——线程取消
    int pthread_cancel(线程ID)
    头文件:#include <pthread.h>
    返回值:成功返回0,失败返回出错编号
  8. pthread_cleanup——线程清理函数
    void pthread_cleanup_pop(决定是否要执行注册函数的关键(非0执行;0不执行))——决定是否使用注册的清理函数
    void pthread_cleanup_push(要注册的清理函数,传递给清理函数的参数)——注册清理函数
    遵循栈的规则,先注册后执行
    头文件:#include <pthread.h>
    返回值:无

线程通信

  1. 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;
}

线程的分离状态

  1. pthread_attr_setdetachstate——设置线程分离状态
    int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
    attr:已初始化的线程属性
    detachstate——分离状态
    1. PTHREAD_CREATE_DETACHED(分离线程)
    2. PTHREAD_CREATE_JOINABLE(非分离线程)、
      头文件:#include <pthread.h>
      返回值:成功返回0,失败返回非0
  2. 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

互斥锁

  1. 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
  2. pthread_mutex_destroy——销毁指定的互斥锁
    int pthread_mutex_destroy(互斥锁地址)
    头文件:#include <pthread.h>
    返回值:成功返回0,失败返回非0
  3. pthread_mutex_lock——对互斥锁上锁,若已上锁则调用者堵塞,直到互斥锁解锁才上锁
    int pthread_mutex_lock(互斥锁地址)
    头文件:#include <pthread.h>
    返回值:成功返回0,失败返回非0
    int pthread_mutex_trylock(互斥锁地址)——不会阻塞
    若互斥锁未加锁,则上锁,返回0;
    若互斥锁已加锁,则函数直接返回失败,即EBUSY
  4. pthread_mutex_unlock——对指定互斥锁解锁
    int pthread_mutex_unlock(互斥锁地址)
    头文件:#include <pthread.h>
    返回值:成功返回0失败返回非0

读写锁

  1. 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
  2. pthread_rwlock_destroy——销毁一个读写锁
    int pthread_rwlock_destroy(读写锁指针)
    头文件:#include <pthread.h>
    返回值:成功返回0,失败返回非0
  3. pthread_rwlock_rdlock——读锁定
    int pthread_rwlock_rdlock(读写锁指针)
    头文件:#include <pthread.h>
    返回值:#成功返回0,失败返回非0
    int pthread_rwlock_tryrdlock(读写锁指针)
    尝试以非阻塞方式在读写锁上获取读锁;若有写者持有或写者堵塞在该读锁,则立即失败返回
  4. pthread_rwlock_wrlock——读锁定
    int pthread_rwlock_wrlock(读写锁指针)
    头文件:#include <pthread.h>
    返回值:#成功返回0,失败返回非0
    int pthread_rwlock_trywrlock(读写锁指针)
    尝试以非阻塞方式在读写锁上获取写锁;若有任何读者或写者该锁,则立即失败返回
  5. pthread_rwlock_unlock——解锁读写锁
    int pthread_rwlock_unlock(读写锁指针)
    头文件:#include <pthread.h>
    返回值:成功返回0,失败返回非0

条件变量

  1. 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

  2. pthread_cond_destroy——销毁一个条件变量
    int pthread_cond_destroy(条件变量指针)
    头文件:#include <pthread.h>
    返回值:成功返回0,失败返回非0

  3. pthread_cond_wait——阻塞等待一个条件变量
    int pthread_cond_wait(指向要初始化的条件变量指针,互斥锁)
    头文件:#include <pthread.h>
    返回值:成功返回0,失败返回非0

  4. pthread_cond_timedwait——限时等待一个条件变量
    int pthread_cond_wait(条件变量指针,互斥锁,const struct.*restrict abstime)
    abstime:绝对时间
    头文件:#include <pthread.h>
    返回值:成功返回0,失败返回非0

    abstime补充说明:
    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);
    
  5. pthread_cond_signal——唤醒阻塞在条件变量上的线程
    int pthread_cond_signal(条件变量指针)
    头文件:#include <pthread.h>
    返回值:成功返回0,失败返回非0

  6. pthread_cond_broadcast——唤醒全部阻塞在条件变量上的线程
    int pthread_cond_broadcast(条件变量指针)
    头文件:#include <pthread.h>
    返回值:成功返回0,失败返回非0

信号量

  1. sem_init——创建一个信号量并初始化它的值,无名信号量在被使用前必须先初始化
    int sem_init(信号量的地址,(填0信号量在线程间共享;填非0信号量在进程间共享),信号量的初始值)
    头文件:#include <semaphore.h>
    返回值:成功返回0,失败返回-1

  2. sem_destroy——删除sem标识的信号量
    int sem_destroy(信号量地址)
    头文件:#include <semaphore.h>
    返回值:成功返回0,失败返回-1

  3. sem_wait——信号量P操作(减1)(会阻塞)
    int sem_wait(信号量地址)
    头文件:#include <semaphore.h>
    返回值:成功返回0,失败返回-1

  4. sem_trywait——信号量P操作(减1)(非阻塞)
    int sem_trywait(信号量地址)
    头文件:#include <semaphore.h>
    返回值:成功返回0,失败返回-1

  5. sem_timedwait——限时尝试将信号量的值减1
    int sem_timedwait(信号量地址,abs_timeout)
    头文件:#include <semaphore.h>
    返回值:成功返回0,失败返回-1

    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秒
    sem_timedwait(&cond, &t);
    
  6. sem_post——信号量V操作(加1)
    int sem_post(信号量的地址)
    头文件:#include <semaphore.h>
    返回值:成功返回0,失败返回-1

  7. 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=&sum;
printf("%d %d %d %d\n",\*p,\*(p+1),\*(p+2),\*(p+3));

IP转换

  1. inet_pton——将点分十进制转换成32位网络大端数据
    int inet_pton((IPV4填AF_INET;IPV6填AF_INET6),点分十进制的首地址,32位网络数据的地址)
    头文件:#include <arpa/inet.h>
    返回值:成功返回1,失败返回0或-1
  2. 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地址
};

作为客户端与服务端通信步骤

  1. 创建套接字:使用 socket 函数创建一个套接字。
  2. 连接服务器:使用 connect 函数连接到服务器。
  3. 发送数据:使用 send 函数发送数据到服务器。
  4. 接收数据:使用 recv 函数接收来自服务器的数据。
  5. 关闭套接字:使用 close 函数关闭套接字。

作为服务端与客户端通信步骤

  1. 创建套接字:使用 socket 函数创建一个套接字。
  2. 绑定地址:使用 bind 函数将套接字绑定到一个地址上。
  3. 监听连接:使用 listen 函数监听来自客户端的连接请求。
  4. 接受连接:使用 accept 函数接受来自客户端的连接请求。
  5. 通信:使用 send 和 recv 函数与客户端进行通信。
  6. 关闭连接:使用 close 函数关闭与客户端的连接。

套接字函数

  1. socket——创建一个新的套接字
    int socket(套接字协议族,套接字类型,具体使用的协议(通常设置为0表示默认协议))
    头文件:#include <sys/socket.h>
    返回值:成功返回一个新的套接字描述符,失败返回-1
  2. connect——连接服务器
    int connect(套接字描述符,服务器的套接字地址,套接字结构体长度)
    头文件:#include <sys/socket.h>
    返回值:成功返回0,失败返回-1
  3. bind——给套接字绑定固定的端口和ip
    int bind(套接字,ipv4套接字结构体地址,结构体长度)
    头文件:#include <sys/socket.h>
    返回值:成功返回0,失败返回-1
  4. listen——监听
    int listen(套接字,已完成队列数之和与未完成队列数之和的最大值(一般填128))
    头文件:#include <sys/socket.h>
    返回值:成功返回0,失败返回-1
  5. 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

数据库

安装:

  1. 服务器的安装:sudo apt-get install mysql-server
  2. 客户端的安装:sudo apt-get install mysql-client
  3. 开发包的安装:sudo apt-get install libmysqlclient-dev
    安装结果检测:netstat -tap | grep mysql

修改密码:

  1. sudo mysql -uroot 回车直接登录
  2. 修改密码:alter user 'root'@'localhost' identified with mysql_native_password by '这里是密码';
  3. 执行:flush privileges;使密码生效,然后使用root用户登录。
  4. 登录 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语法的增删改查排序

显示

  1. 显示目前所有的数据库
    show databases; //显示目前所有的数据库(文件夹)
  2. 显示数据库中的表
    show tables from xxx(某个数据的名字); //显示某个数据库里面的所有的表
    show tables; //显示你正在使用的数据库的表
  3. 选中数据库 // 必须已经选中某个数据库使用 -- use xxx(数据库名字)
    use xxx(数据库的名字) //选中某个数据库
  4. 显示表里面的列信息(表头!)
    show columns from xxx(某个表) //已经有选中的数据库了 //不然你要指定数据
    show columns from xxx(某个表)from xxx(某个数据库) //显示任意数据库里面任意表的表头信息

查找

  1. select * from xxx表 //显示表里面的所有内容
  2. select name,age,new_sex from xxx表 //我仅仅想显示 这三列
  3. select name,age,new_sex from new_my_pet where age < 18 AND new_sex = 'w'; //显示 三列信息 且 性别是女 且 年龄小于18

增加

创建数据库
创建表必须加表头信息
增加数据信息

  1. 创建一个数据库
    create database [db_name]; //创建一个名字叫做 db_name的数据库
  2. 创建表 ---- 必须加表头信息
    create table [table_name](name CHAR(20),id INT,sex CHAR,aihao CHAR(20),birth DATE,death DATE)
  3. 添加表里面的信息--- insert --插入
    insert into my_pet values('zhangsan',1,'m','play game','1990-08-01',NULL); //插入的信息要跟表头一一对应

修改

  1. 改表的名字
    alter table tbl_name(之前的表名) rename new_tbl(新的表名)
    alter table my_pet rename new_pet; //把 my_pet 改成 new_pet 名字
  2. 增加一列
    alter table new_pet add age TINYINT; //给new_pet 增加一列 age 类型是 TINYINT
  3. 删除列
    alter table new_pet drop age; //把 new_pet 表里 的age列删除
  4. 改数据的信息(update)
    update new_pet set death = '2021-07-26' where name = 'zhangsan' //把 'zhangsan' 的 death设置为 '2021-07-26'

删除

delete drop

  1. 删除一个数据库
    drop database [数据库的名字]
  2. 删除一个表格
    drop table [表的名字]
  3. 如何删除列
    alter table new_pet drop age; //把 new_pet 表里 的age列删除
  4. 删除一行数据
    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

相关文章

  • 《流畅的Python第二版》读书笔记——文本和字节序列
    引言这是《流畅的Python第二版》抢先版的读书笔记。Python版本暂时用的是python3.8。为了使开发更简单、快捷,本文使用了JupyterLab。Python3明确区分了人类可读的字符串和原始的字节序列。新内容简介新增了对emoji表示字符的描述。字符问题字符串是个简单的概念:一个字符串是一个字......
  • java-房屋出租系统实现
    房屋出租系统项目需求能够实现对房屋信息的添加、修改和删除(用数组实现),并能够打印房屋明细表项目界面主菜单新增房源查找房源删除房源修改房源房屋列表退出系统项目设计项目实现显示主菜单在HouseView.java中,编写一个方法mainMenu,显示菜单点击查看代码......
  • C和C++进阶的学习笔记总结目录
    C语言–C语言基础知识积累记录学习教程:参考C++教程网之跟我一起学Cdo{…}while(0)的用途汇总(欢迎补充)在一些Linux内核和其它的开源代码中可见到【C语言】《带你学C带你飞》,笔记:链接––C++–一张图总结GoogleC++编程规范(GoogleC++StyleGuide)C++基础学习目录总结参考:链......
  • 操作系统概述
    2.1.1操作系统的概念操作系统 是一组控制盒管理计算机系统的硬件和软件资源、控制程序执行、改善人机界面、合理地组织计算机工作流程并未用户使用计算机提供良好运行环境的一种系统软件。 目的:提高计算机系统的效率,增强系统的处理能力,提高系统资源的利用率,方便用户使用计算机。2......
  • 语义检索系统:基于Milvus 搭建召回系统抽取向量进行检索,加速索引
    语义检索系统:基于Milvus搭建召回系统抽取向量进行检索,加速索引目标:使用Milvus搭建召回系统,然后使用训练好的语义索引模型,抽取向量,插入到Milvus中,然后进行检索。语义搜索系列文章全流程教学:语义检索系统:基于无监督预训练语义索引召回:SimCSE、Diffcse:语义检索系统:基于in......
  • 语义检索系统之排序模块:基于ERNIE-Gram的Pair-wise和基于RocketQA的CrossEncoder训练
    语义检索系统之排序模块:基于ERNIE-Gram的Pair-wise和基于RocketQA的CrossEncoder训练的单塔模型文本匹配任务数据每一个样本通常由两个文本组成(query,title)。类别形式为0或1,0表示query与title不匹配;1表示匹配。基于单塔Point-wise范式的语义匹配模型ernie_matchi......
  • 语义检索系统:基于无监督预训练语义索引召回:SimCSE、Diffcse
    基于无监督预训练语义索引召回:SimCSE、Diffcse语义索引(可通俗理解为向量索引)技术是搜索引擎、推荐系统、广告系统在召回阶段的核心技术之一。语义索引模型的目标是:给定输入文本,模型可以从海量候选召回库中快速、准确地召回一批语义相关文本。语义索引模型的效果直接决定了语义相......
  • Linux pinctrl 子系统
    文章代码分析基于linux-5.19.13,架构基于aarch64(ARM64)。1.Linux5.x官方参考文档Documentation\devicetree\bindings\pinctrl\pinctrl-bindings.txt2.Pinctrl的引入 想要pinA、B用于GPIO,需要设置IOMUX让它们连接到GPIO模块;要想让pinA、B用于I2C,需要设置IOMUX让它们连接......
  • 《深度管理》读书笔记1
    书籍信息参考:https://book.douban.com/subject/30258984/ 一 “赢得漂亮”意味着你能长时间地维持优秀的业绩,因为你拒绝屈服于严酷而招致压力的捷径,暂时将他人当成业绩的牺牲品。你需要让精力充沛、鼓足干劲的人们共同工作。你的策略的强大取决于你的团队在第一线的执行力,要......
  • [刷题笔记] Luogu P1853 投资的最大效益
    ProblemSolution刚开始看这道题的时候不自主的想到了纪念品,但其实本题和纪念品还是有区别的。纪念品规定了每次只能买一个纪念品,而本题可以买无限个纪念品需要在原本的基础上买进卖出,钱有进有出,而本题时只有进,稳赚不赔。本题和纪念品不同的第一点决定了它时完全背包,纪念品......