Linux服务器开发-基础教程总结(1)-基础教程

前言

本篇文章是观看视频所做的一些笔记。

正文

1. 使用tar对文件进行压缩

tar 参数: 不使用z/j 参数 命令只能对文件或目录打包

  1. c——创建——压缩
  2. x——释放——解压缩
  3. v——显示提示信息——压缩解压缩 可省略
  4. f——指定压缩文件的名字

z-——使用gzip的方式压缩文件 .gz
j——使用 bzip2的方式压缩文件 .bz2

压缩:
tar zcvf 生成的压缩包的名字(xxxx.tar.gz)
tar jcvf 生成的压缩包的名字(xxx.tar.bz2)

2. gcc的整个编译过程

预处理->编译->汇编->链接

编译期间是最耗时的。

  1. 这个编译过程很简单,我用罗列的方式应该就看起来简单很多了。
    首先,准备一个main.c ,我相信这个过程应该大家都是会的。然后正式开始编译:

gcc -E main.c -o main.i
gcc -S main.i -o main.s
gcc -c main.s -o main.o
gcc main.o -o main
最后直接执行这个./main即可。

看出来猫腻了吗,那个参数分别是E S c . -o 表示的是要生成的文件的名称,分别是i ,s ,o 。就这样记忆应该就可以记录下来了。

当然上面这个过程只是让你了解gcc编译的而整个过程,而实际上,你可以直接用一条指令就可以解决这样的问题了。

gcc main.c -o main

直接一条命令就可以将main.c 编译成功了。

3. gcc的其他一些参数:

-I : 指定头文件的路径
-D: 指定一个宏,相当于在文件中define 了一个宏。
-Wall :编译期间输出警告
-g:gdb调试时需要该参数
-L :后面接要依赖的库的目录
-l: 后面接具体依赖的库的名字,注意要去掉lib这个前缀。
-fPIC:就可以生成与位置无关的代码
-O(1-3):表示优化的级别 -O1 或-O2 或-O3

4. lib静态库文件

制作步骤:

  1. 生产对应的.o文件 —>c -o -c
  2. 将生成的.o文件打包 ar rcs+静态库的名字(libMytest.a)+生成的所有的.o

使用: main.c -L -l
gcc main.c -LlibPath -llibName -o app -Iinclude

发布 和使用静态库
3. 发布.a文件
4. 给.h文件

优点:
5. 由于静态库以及被打包到可执行文件中了,所以,在发布的时候就不用再发布静态库了。
6. 加载库的速度快。

缺点 :
7. 可执行文件中会变大。
8. 升级很麻烦,需要重新编译程序。

5. 共享库(动态库)

  1. 命令规则

lib +名字+ .so

  1. 制作步骤

生成与位置无关的代码(生成与位置无关的.o)
gcc -fPIC -c *.c -Iinclude
将.o打包成共享库

  1. 打包方式

gcc -shared -o lib名字.so *.o

  1. 使用方式

gcc main.c lib/libmy.so -o app
gcc main.c -LlibPath -lmytest -Iinclude -o app

  1. 查找依赖的库

ldd myApp
一般是先去查找环境变量

  1. 应用程序不能执行,动态连接器连接不到自己制作的库
  1. 临时设置的方法
    export LD_LIARARY_PATH = ./lib
  1. 永久设置的方法
  2. 找到动态链接库的配置文件:/etc/ld.so.conf
  3. 在该文件中添加动态库的目录(绝对路径)
  4. 更新 :sudo ldconfig -v

6. GDB调试

  1. 注意使用gcc编译程序的时候要使用-g的选项,才会是生成的可执行文件里面有行号,才可以进行操作。
  1. l :显示程序
  2. b num: 打断点
  3. i: info的意思
  4. i b: 代表显示出断点信息
  5. start :让程序启动,会开始跑到断点的那个地方
  6. n:next就是一步一步向后走,直接就执行完函数体了
  7. c: 就是continue 继续跑
  8. s: step进入到函数体的内部
  9. p: printf 表示的是打印某个变量
  10. ptype: 显示某个变量的类型
  11. start和run的区别:默认情况下,run 指令会一直执行程序,直到程序执行结束。如果程序中手动设置有断点,则 run 指令会执行程序至第一个断点处. start 指令会执行程序至 main() 主函数的起始位置,即在 main() 函数的第一行语句处停止执行(该行代码尚未执行)。
  12. file 文件名(绝对路径): 可以通过file命令指定要进行gdb调试的文件。
  13. –args: 指定需要传递给程序的数据
  14. set args: 可以借助 set args 命令指定目标调试程序启动所需要的数据
  15. run® 数据:可以使用run 或者start启动目标程序时,指定其所需要的数据。
  16. cd /tmp/demo :将 GDB 调试器的工作目录修改为 /tmp/demo
  17. path /temp/demo :某些场景中,目标调试程序的执行还需要临时修改 PATH 环境变量,此时就可以借助 path 指令
  18. run >a.txt: 通过run > 可以将运行的程序的输出结果输出到a.txt.
  19. watch cond: watch 称为监控断点,cond 表示要监控的变量
  20. catch event:建立捕捉断点的方式很简单
  21. catch 库的名称:监控库的加载(使用ldd App 可以获知其运行所需加载的动态库)
  22. break … if cond: 在某种条件下使断点发挥其作用。
  23. condition bnum expression:参数 bnum 用于代指目标断点的编号;参数 expression 表示为断点添加或修改的条件表达式。用于为 bnum 编号的断点添加或修改 expression 条件表达式
  24. condition bnum:用于删除 bnum 编号断点的条件表达式,使其变成普通的无条件断点
  25. ignore bnum count: 参数 bnum 为某个断点的编号;参数 count 用于指定该断点失效的次数。仅为一个整数,它用来表示该断点失效的次数
  26. next,step,until :都可以控制GDB调试器每次只执行一行代码。
  27. step next基本相同:但当step遇到函数时,会进入到函数内部,并在函数第一行代码处停下。
  28. until:不带参数的 until 命令,可以使 GDB 调试器快速运行完当前的循环体,并运行至循环体外停止。注意,until 命令并非任何情况下都会发挥这个作用,只有当执行至循环体尾部(最后一行代码)时,until 命令才会发生此作用。
  29. until location:location只是行号。
  30. finish:如果是在循环体内非最后一次循环,直接finish是出不来的。可以把循环的位置的断点去掉。就可以跳出函数体了。
  31. set var 变量名= 赋值:设置变量的值
  32. display 变量名:自动打印变量值,设置追踪变量
  33. undisplay:取消追踪变量
  34. info display:获取编号
  35. u: 跳出循环的命令
  36. quit:退出gdb

7. MakeFile

基础知识

  1. makefile中的shell的含义:

  2. 在规则中需要使用符号 本 身 的 地 方 , 需 要 书 写 两 个 连 续 的 本身的地方,需要书写两个连续的 $

  3. $? 表示比目标还要新的依赖文件列表

  4. 分号是分隔符,反斜线是换行符,反斜杠是转义字符。

  5. CUR_C := $(filter %.c, ( C U R S R C ) ) : 过 滤 掉 所 有 (CUR_SRC)):过滤掉所有 (CURSRC)):(CUR_SRC)里面不符合%.c的文件 “filter”函数可以用来去除一个变量中的某些字符串.

  6. cat 111.txt | tr [a-z] [A-Z] > 222.txt:tr命令用于转换文本文件中的字符

  7. $(strip STRINT)
    函数名称:去空格函数—strip。
    函数功能:去掉字串(若干单词,使用若干空字符分割) “STRINT”开头和结尾的
    空字符,并将其中多个连续空字符合并为一个空字符。
    返回值:无前导和结尾空字符、使用单一空格分割的多单词字符串。
    函数说明:空字符包括空格、[Tab]等不可显示字符。

  8. $1表示取值

  9. $(foreach var text commond):
    var:局部变量
    text:文件列表,空格隔开,每一次取一个值赋值为变量var
    commond:对var变量进行操作(一般会使用var变量,不然没意义),每次操作结果都会以空格隔开,最后返回空格隔开的列表。

  10. call:call函数是唯一一个可以用来创建新的参数化的函数。 ( c a l l < e x p r e s s i o n > ; , < p a r m 1 > ; , < p a r m 2 > ; , < p a r m 3 > ; . . . ) 当 m a k e 执 行 这 个 函 数 时 , < e x p r e s s i o n > ; 参 数 中 的 变 量 , 如 (call <expression>;,<parm1>;,<parm2>;,<parm3>;...) 当make执行这个函数时,<expression>;参数中的变量,如 (call<expression>;,<parm1>;,<parm2>;,<parm3>;...)make<expression>;(1), ( 2 ) , (2), (2)(3)等,会被参数< parm1>;,;,;依次取代。而;的返回值就是 call函数的返回值。

  11. =:代表的是赋值的意思:OBJECTS=$(SOURCES:.cpp=.o):代表的是将SOURCES 中的.o都代替成.cpp。

  12. wildcard取所有目录下的.c文件。

  13. 四种赋值方式
    简单赋值 ( := ) 编程语言中常规理解的赋值方式,只对当前语句的变量有效。
    递归赋值 ( = ) 赋值语句可能影响多个变量,所有目标变量相关的其他变量都受影响。
    条件赋值 ( ?= ) 如果变量未定义,则使用符号中的值定义变量。如果该变量已经赋值,则该赋值语句无效。
    追加赋值 ( += ) 原变量用空格隔开的方式追加一个新值。
    在这里插入图片描述

  14. makefile 的编写
    规则的三要素:目标,依赖,命令
    目标:依赖条件
    命令
    一定要有个TAP键
    在这里插入图片描述

  15. 在MakeFile中如果有多条规则的话,那么默认第一个目标就是终极目标。

  16. 为了防止每次修改一个就得 全部都编译,就把依赖的目标更改为.o文件。

  17. 工作原理:
    在这里插入图片描述
    makefile版本

  18. 版本一:

app:main.c add.c sub.c mul.c
	gcc main.c add.c sub.c mul.c -o app
  1. 版本二:
  2. 版本三:使用变量名代表一系列名字 target:目标
    app: main.o add.o sub.o
    gcc main.o sub.o mul.o -o app
    %.o:%.c ->会在找main.o找不到的时候,自动把main填入达到%里面。
    makefile中的自动变量:

$<: 规则中的第一个依赖
$@:规则中的目标
$^:规则中的所有依赖
只能在规则的命令中使用。
在这里插入图片描述

  1. 版本四:
#makefile自己维护的变量
CC=cc
# CPPFLAGS:
CPPFLAGS = 
# 这里的cc其实就是gcc


5. 版本五:

在这里插入图片描述

  1. makefile给我们提供的函数都是返回值的。
  2. wildcard:获取指定目录下的.c文件:wildcard
  3. pastsubst:把指定目录下的.c 文件替换成.o。 这里模式匹配使用的是%,不是*。
  4. 给makefile提供函数传参,只需要将其参数与函数名用空格分离即可。但参数和参数之间使用逗号进行间隔。
  5. 取变量里面的内容记得要加$。
  6. 这样获取到的obj,就可以获取一系列函数的.o文件名字的集合。
  1. 版本六:Clean目标的加入
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

1.-rm :这个-的含义就是忽略掉当前命令执行失败的情况。
2. 查找指定目录下,指定类型的文件: src = $(wildcard ./*.c);
3. 匹配替换函数:obj = ( p a t s u b s t (patsubst %.c,%.o, (patsubst(src);
4. .PHONY:这个的意义是,这个是个伪目标,所以,即使当前文件夹中存在clean这个文件,也依然会执行clean下面的语句。

三个自动变量:

  1. $<: 规则中的第一个依赖
  2. $^:规则中的所有依赖
  3. $@:规则中的目标

8. C库函数

在这里插入图片描述

在这里插入图片描述

  1. 与位置无关的代码:

在这里插入图片描述

  1. #define NULL (void *)0 :这里的NULL其实就在受保护的地址
  2. 为什么要弄一个虚拟地址空间:
    在这里插入图片描述
  3. 虚拟地址空间,注意虚拟的含义。

9. 库函数与系统函数之间的关系

在这里插入图片描述

  1. FD:文件描述符 FD_POS:文件指针 BUFFER:buffer
    2.write:做一个将用户空间拷贝到内核空间

10. open函数的使用

  1. 举个例子
    在这里插入图片描述

在这里插入图片描述

11. read函数的使用

在这里插入图片描述

返回值:

  1. -1 :读取失败
  2. 0:文件读完了。
  3. 正数:文件读取上来的字节数。

12. readAndWrite函数的应用

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
        //打开一个已经存在的文件
        int fd = open("file.txt",O_RDONLY);
        if(fd==-1)
        {
                perror("open");
                exit(1);
        }
        //创建一个新文件---写操作
        int fd1 = open("newfile",O_CREAT|O_WRONLY,0664);
        if(fd1==-1)
        {
                perror("open1");
                exit(1);
        }
        //read file
        char buf[2048]={0};

        int count = read(fd,buf,sizeof(buf));
        if(count==-1)
        {
                perror("read");
                exit(1);
        }
        while(count)
        {
                //将读出的数据写入到另一个文件中国
                int ret =write(fd1,buf,count);
                printf("write bytes %d\n",ret);
                count = read(fd,buf,sizeof(buf));
        }
        //close file
        close(fd);
        close(fd1);
        return 0;
}

作用:将某个文件中的内容读取到另一个文件中的内容,新创建的一个文件。

13.lseek

  1. 获取文件大小
  2. 移动文件指针
  3. 文件拓展

应用

#include <stdlib.h>

int main()
{
        int fd = open("aa",O_RDWR);
        if(fd==-1)
        {
                perror("open file");
                exit(1);
        }
        int ret  = lseek(fd,0,SEEK_END);
        printf("file length=%d\n",ret);

        //文件拓展
        ret = lseek(fd,2000,SEEK_END);
        printf("return value:%d\n",ret);

        //实现文件拓展,需要再最后做一次写操作
        write(fd,"a",1);
        close(fd);
        return 0;
}

  1. 注意,在使用lseek进行拓展后,一定要额外进行一次拓展。不然,是没办法完成拓展操作的。

14. stat函数

依赖的头文件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这个的含义就是追踪和不追踪的意思。意思就是在遇到软链接的时候,是否会追踪到最底下的文件进行硕源。
stat是一个穿透的函数。
在这里插入图片描述

  1. 带l的是不穿透的。

15. access

在这里插入图片描述

成功就是0,不成功就返回-1。

16. truncate

在这里插入图片描述

17. link

在这里插入图片描述
unlink的应用

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
        int fd = open("tempfile",O_CREAT|O_RDWR,0664);
        if(fd==-1)
        {
                perror("open");
                exit(1);
        }
        //删除临时文件file
        int ret = unlink("tempfile");
        //write file
        write(fd,"hello\n",6);
        //重置文件指针
        lseek(fd,0,SEEK_SET);
        //read file
        char buf[24] = {0};
        int len =       read(fd,buf,sizeof(buf));
        //将读出的内容,写到屏幕上
        write(1,buf,len);

        //close file
        close(fd);
        return 0;
}

18. 常用命令

在这里插入图片描述

rename
int rename(const char*oldpath,const char* newpath);

chdir
改变进程的路径
getcwd
获取当前进程目录

rmdir
删除空目录
opendir
打开一个目录
在这里插入图片描述

在这里插入图片描述
readdir
在这里插入图片描述
应用

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>

int getFileNum(char* root)
{
        //open dir
        DIR* dir = NULL;
        dir = opendir(root);
        if(dir==NULL)
        {
                perror("opendir");
                exit(1);
        }
        //遍历当前打开的目录
        struct dirent* ptr = NULL;
        char path[1024];
        while(ptr=readdir(dir)!=NULL)
        {
                //过滤,和
                if((strcmp(ptr->d_name,".")==0)||(strcmp(ptr->d_name,".."==0))
                {
                        continue;
                }
                if(ptr->d_type==DT_DIR)
                {
                        //递归 读目录
                        sprintf(path,"%s/%s",root,ptr->d_name);
                        total += getFileNum(path);
                }
                //如果是普通文件
                if(ptr->d_type==DT_REG)
                {
                        total++;
                }
        }
        closedir(dir);//一定要关掉目录
        return total;
}

int main(int argc,char * argv[])
{
        if(argc<2)
        {
            printf("./a.out dir\n");
        }
        int total = getFileNum(argv[1]);
        printf("-->z %s has file numbers%d\n",argv[1],total);
        return 0;
}

19. dup,dup2(复制现有的文件描述符)

在这里插入图片描述
dup返回的就是文件描述符中没有被占用的最小的文件描述符。

20. fcntl

在这里插入图片描述

在这里插入图片描述

改变已经打开的文件的属性

总结

这个Linux服务器开发-基础教程总结(1) 视频到这就结束了,基本上把一些Linux开发的一些基本技能都展示了一下,师傅领进门修行在个人。接下来,就得靠自己去不断的熟练这些东西。接下来,开始看(2)的,就开始接触进程的一些概念了。

参考

  1. C/C++高级编程系列(1)之Linux服务器开发一基础教程
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值