Linux高并发服务器开发-Linux系统编程入门

环境准备

Ubuntu18
Xshell
Xftp
VsCode

vscode ssh 远程连接ubuntu

报错 过程试图写入管道不存在

替换ssh路径

这是我自己解决的方法,可能是因为win10内置的SSH的问题,由于装了Git,且自带ssh,因此可以在环境变量中将win10内置ssh的路径替换为git的

环境变量——系统变量——path

查找ssh路径

git bash here
where ssh

我自己的环境变量

%SYSTEMROOT%\System32\OpenSSH\

将其替换为git的ssh路径

GCC

安装命令 (version>4.8.5)

sudo apt install gcc g++ 

查看版本

gcc/g++ -v/--version

编译

g++ test.c -o app

工作流程

预处理器

编译器

汇编器

链接器

链接器

链接器

链接器

源代码.h.c.cpp

预处理后源代码.i

汇编代码.s

目标代码

启动代码

可执行程序.exe.out

库代码

其他目标代码

gcc编译选项 说明
-E 预处理指定的源文件,不进行编译
-S 编译指定的源文件,但是不进行汇编
-c 编译、汇编指定源文件,但不链接
-o 将file1编译成可执行文件file2
-I 指定include包含文件的搜索目录
-g 在编译的时候,生成调试信息,程序可以被调试器调试
-D 在程序编译的时候,指定一个宏
-w 不生成任何警告信息
-Wall 生成所有警告信息
-l 在程序编译的时候,指定使用的库
-L 指定编译时搜索的库的路径
-shared 生成共享目标文件,通常在建立共享库时
-fpic/-fPIC 生成与位置无关的代码

gcc 和 g++的区别

Alt text

_cplusplus宏只标志编译器把代码按照C还是C++解释,如果是.c 并且采用gcc编译,该宏就是未定义,否则就是已定义的

编译可以用gcc/g++,链接可以用gcc/gcc -lstdc++
gcc命令不能自动和C++程序的库链接,通常用g++,编译阶段,g++会自动调用gcc,二者等价

动态库和静态库

命名规则

  1. Linux:

    1. libxxx.a(静态库)
    2. libxxx.so(动态库)
  2. Windows

    1. libxxx.lib(静态库)
    2. libxxx.dll

静态库和动态库的制作

gcc获得.o文件

静态库

gcc -c xxx.c xxx.c xxx.c

动态库,得到和位置无关的代码

gcc -c -fpic/-fPIC xxx.c xxx.c

打包.o文件

静态库ar工具(achieve)打包

ar rcs libxxx.a xxx.o xxx.o xxx.o 
    r- 将文件插入备存文件中
    c- 建立备存文件
    s- 索引

动态库

gcc -shared xxx.o xxx.o -o libxxx.so

静态库和动态库的使用

Alt text
以此为例

静态库的使用

gcc main.c -o app -I ./include/ -l calc -L./lib

动态库的使用

Alt text

gcc main.c -o app -I ./include/ -l calc -L./lib

动态库使用需要动态载入才能使用,不推荐修改 /lib/, /usr/lib目录,因为里面有系统的库。

方法1,添加环境变量 LD_LIBRARY_PATH

显示动态库的依赖关系
ldd app

查看环境变量
env

添加环境变量
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/xxx/xxx/xxx/lib

显示添加的环境变量的值
echo $LD_LIBRARY_PATH

运行更新配置: 
source xxx
  1. 临时配置:程序文件夹library目录下配置
  2. 永久配置:
    1. 用户级别:在 home目录下,.bashrc里配置
    2. 系统级别:在 /etc/profile里配置

方法2,修改 /etc/ld.so.cache文件列表

sudo vim /etc/ld.so.conf

添加lib的路径

sudo ldconfig

静态库和动态库的对比

Alt text

静态库优缺点

Alt text

动态库优缺点

Alt text

Makefile

自动化编译,定义一系列规则指定文件编译顺序等。通过make命令,整个工程完全自动编译。

规则

一个Makefile文件可以有一个或多个规则

目标... : 依赖...
    命令(shell命令)
    ...

Makefile 中的其他规则一般是为第一条规则服务的

工作原理

Alt text

变量

Alt text

模式匹配

%.o:%.c
    - %: 通配符,匹配一个字符串
    - 两个%匹配同一个字符串

%.o:%.c
    gcc -c $< -o $@

函数

$(wildcard PATTERN...)

Alt text

$(patsubst <pattern>,<replacement>,<text>)

Alt text

clean

.PHONY:clean    //clean伪目标,不生成特定的文件
clean:
    rm ... -f

执行 
make clean

GDB调试

GDB的功能

Alt text

准备工作

关闭编译器优化选项(-O),打开调试选项(-g), '-Wall' 尽量在不影响程序行为的情况下打开所有warning。

gcc -g -Wall program.c -o program

'-g' 作用是在可执行文件中加入源代码的信息,比如可执行文件中第几条机器指令对应源代码的第几行,并不是把整个源代码嵌入可执行文件中,所以在调试时必须保证gdb能找到源文件。

GDB命令-启动、退出、查看代码

Alt text

GDB命令-断点代码

Alt text

GDB命令-调试命令

Alt text

文件IO相关

标准C库IO函数

Alt text

标准C库IO函数与Linux系统IO函数的关系

Alt text

虚拟地址空间

Alt text

文件描述符

Alt text

Linux系统文件IO相关函数

Alt text

open(), close()

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//打开一个已存在的文件
int open(const char*pathname, int flags);
    参数:
        -pathname:要打开的文件路径
        -flags:对文件操作权限设置还有其他设置
        O_RDONLY, O_WRONLY, O_RDWR 三个设置互斥
    返回值:返回一个新的文件描述符,调用失败,返回-1
errno:属于linux系统函数库,库里面一个全局变量,记录最近的错误号
#include...
//创建一个新文件
int open(const char *pathname, int flags, mode_t mode);
    参数:
        -flags:对文件操作权限设置还有其他设置
            -必须项:O_RDONLY, O_WRONLY, O_RDWR 三个设置互斥
            -可选项:O_CREAT 文件不存在,创建新文件
            flags参数是一个int数据,占4个字节,32位,每一位就是一个标志位
        -mode:八进制的数,表示创建出的新的文件的操作权限
            最终的权限:mode& ~umask 
            mode:比如:0775  
               000 111 111 101
               rwx rwx rwx rwx
                0   7   7   5

int fd = open("creat.txt", O_RDWR|O_CREAT, 0777);  
#include<stdio.h>
//打印errno对应的错误描述
void perror(const char*s);
    s参数:用户描述,比如hello,最终输出hello:xxx(实际错误信息)
#include<unistd.h>
int close(int fd);
    fd:文件描述符

read(),write()

#include <unistd.h>
//读文件
ssize_t read(int fd, void *buf, size_t count);
    参数:
        -fd:文件描述符,open得到,通过文件描述符操作这个文件
        -buf:需要读取数据存放的地方,数组的地址(传出参数)
        -count:指定的数组的大小
    返回值:
        -成功:
            >0:返回实际读取到的字节数
            =0:文件已经读取完
        -失败:-1,并且设置errno

//写文件
ssize_t write(int fd, const void *buf, size_t count);
    参数:
        -fd:文件描述符,open得到,通过文件描述符操作这个文件
        -buf:需要往磁盘写入的数据
        -count:写入的数据的实际大小
    返回值:
        -成功:实际写入的字节数
        -失败:-1,并设置errno
//频繁读写操作
char buf [1024]={0};
int len=0;
while((len=read(fd1,buf,sizeof(buf)))>0){
    write(fd2,buf,len);
}

lseek()

//标准C库的函数
#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);
//Linux系统函数
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
    参数:
        -offset:偏移量
        -whence:
            SEEK_SET
                设置文件指针偏移量
            SEEK_CUR
                设置偏移量:当前位置+第二个参数offset的值
            SEEK_END
                设置偏移量,文件大小+第二个参数offset的值
    返回值:返回文件指针的位置

    作用:
        1.移动文件指针到头文件
            lssek(fd,0,SEEK_SET);
        2.获取当前文件指针的位置
            lseek(fd,0,SEEK_CUR);
        3.获取文件的长度
            lseek(fd,0,SEEK_END);
        4.扩展文件的长度,当前文件10b -> 110b,增加了100个字节
            lseek(fd,100,SEEK_END);
        注意;扩展文件后,写入数据。

stat(),lstat()

Alt text
Alt text

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
//获取一个文件相关的信息
int stat(const char *pathname, struct stat *statbuf);
    参数:
        -statbuf:结构体变量,传出参数,用于保存获取的文件信息
    返回值
        -成功:返回0
        -失败:返回-1,并设置errno

//获取软链接文件的信息
int lstat(const char *pathname, struct stat *statbuf);

文件属性操作函数

Alt text

access()

 #include <unistd.h>
//判断文件是否有某个权限
int access(const char *pathname, int mode);
    参数:
        -mode:
            R_OK:判断是否有读权限
            W_OK:判断是否有写权限
            X_OK:判断是否有执行权限
            F_OK:判断文件是否存在
    返回值:
        -成功:返回0
        -失败:返回-1

chmod(), chown()

#include <sys/stat.h>
//修改文件的权限
int chmod(const char *pathname, mode_t mode);
    参数:
        -mode:需要修改的权限值,八进制数
    返回值:
        -成功:返回0
        -失败:返回-1
 #include <unistd.h>
//修改文件owner,group
int chown(const char *pathname, uid_t owner, gid_t group);
    参数:
        -owner:所有者id
        -group: 所在组id

truncate()

#include <unistd.h>
#include <sys/types.h>
//缩减或扩展文件的尺寸至指定的大小
int truncate(const char *path, off_t length);
    参数:
        -length:最终文件变成的大小
    返回值:
        -成功:返回0
        -失败:返回-1

目录操作函数

Alt text

mkdir(), rmdir()

#include <sys/stat.h>
#include <sys/types.h>
//创建一个目录
int mkdir(const char *pathname, mode_t mode);
    参数:
        -mode:需要修改的权限值,八进制数
    返回值:
        -成功:返回0
        -失败:返回-1
#include <unistd.h>
//只能删除一个空目录
int rmdir(const char *pathname);

rename()

#include <stdio.h>
//重命名目录
int rename(const char *oldpath, const char *newpath);

chdir(), getcwd()

#include <unistd.h>
//修改进程的工作目录
int chdir(const char *path);
#include <unistd.h>
//获取当前工作目录
char *getcwd(char *buf, size_t size);
    参数:
        -buf:
            存储的路径,执行一个数组
        -size:
            数组的大小
    返回值:返回的指向一块内存,这个数据就是第一个参数

目录遍历函数

Alt text

opendir()

#include <sys/types.h>
#include <dirent.h>
//打开一个目录
DIR *opendir(const char *name);
    参数:
        -name:需要打开的目录名称
    返回值:
        DIR*类型,目录流信息。
        错误返回NULL

readdir()

#include <dirent.h>
//读取目录中的数据
struct dirent *readdir(DIR *dirp);
    参数:
        -dirp:dirp是opendir返回的结果
    返回值:
        struct dirent ,代表读取文件的信息
        失败返回NULL

Alt text

closedir

#include <sys/types.h>
#include <dirent.h>
//关闭目录
int closedir(DIR *dirp);

文件描述符函数

dup(),dup2()

#include <unistd.h>
//复制文件描述符
int dup(int oldfd);
 

//重定向文件描述符号
int dup2(int oldfd, int newfd);
    oldfd必须有效

fcntl()

#include <unistd.h>
#include <fcntl.h>
//
int fcntl(int fd, int cmd, ... /* arg */ );
    参数:
        -cmd:对文件描述符如何操作
            -F_DUPFD : 复制文件描述符,复制的第一个参数fd,得到一个新的文件描述符(返回值)
                int ret = fcntl(fd,F_DUPFD);

            -F_GETFL : 获取指定的文件描述符文件状态flag,获取的flag和open函数的flag相同

            -F_SETFL : 设置文件描述符文件状态flag
                必选项:O_RDONLY,O_WRONLY,O_RDWR不可以被修改
                可选项:O_APPEND,O_NONBLOCK
                    O_APPEND 表示追加数据
                    O_NONBLOCK 设置成非阻塞
                int flag = fcntl(fd, F_GETFL);
                flag |= O_APPEND;
                int ret  = fcntl(fd, F_SETFL, flag)
posted @   玩世不恭xxh  阅读(43)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示