【C++】Linux系统编程入门

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:开发工具(Ubuntu+Xshell+VS Code)

一 常用的Linux系统命令符

ls ——查看当前目录下的文件
pwd ——看当前所在文件夹


cp calc library ../lession06 -r 
//-r ,目录文件,递归调用
//cp,copy文件


rm+文件名.后缀/*.后缀 	//删除当前目录下的文件
touch  name.txt
mkdir name //创建文件夹

ln -s a.txt b.txt  //创建软链接

ls -l  //当前目录所有文件信息

env //查看系统变量

二 GCC

gcc *.c -o app(可执行文件名)

三 静态库

四 动态库(共享库)

动态库

◼ 命名规则:

◆ Linux : **lib*xxx*.so**
	lib : 前缀(固定)
	xxx : 库的名字,自己起(使用库时的用名)
	.so : 后缀(固定)
	在Linux下是一个可执行文件

◆ Windows : **lib*xxx*.dll**

◼ 动态库的制作:

◆ gcc 得到 .o 文件,得到和位置无关的代码(–fpic)
	gcc -c –fpic/-fPIC a.c b.c
	
◆ gcc 得到动态库
	gcc -shared a.o b.o -o libcalc.so

◼ 动态库加载失败的原因:

◆ 动态库:gcc进行链接时,动态库的代码不会被打包到可执行文件中,(只包含动态库的一些信息)

◆ 编译时不报错是因为只是把动态库的信息放到可执行程序中,没有加载动态库的内容到内存中。

◆运行时找不到动态库——没有指明动态库的绝对路径

◆如何定位共享库文件呢?
	当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径。
此时就需要系统的动态载入器来获取该绝对路径。
对于elf格式的可执行程序,是由ld-linux.so来完成的,
它先后搜索elf文件的 DT_RPATH段 (无法改变)
——> 环境变量LD_LIBRARY_PATH
 ——> /etc/ld.so.cache文件列表
 ——> /lib/,/usr/lib目录找到库文件后将其载入内存。

◼ 动态库加载失败的解决方法(配置环境变量):

方法一:环境变量LD_LIBRARY_PATH

◆终端下配置环境变量(临时性)
	 echo $LD_LIBRARY_PATH:/home/coder/Linux/lession06/library/lib
·◆用户级别的配置环境变量(永久性)
	 vim .bashrc  (根目录下打开并添加以下环境变量)
	export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:
	/home/coder/Linux/lession06/library/lib

	. .bashrc 或 source .bashrc  (使得环境变量生效)

◆系统级别的配置环境变量(永久性)
		sudo vim /etc/profile
		export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:
	/home/coder/Linux/lession06/library/lib
	
	source /etc/profile    //刷新

方法二:/etc/ld.so.cache文件列表

	sudo vim /etc/ld.so.conf
	/home/coder/Linux/lession06/library/lib

	sudo ldconfig

五 动态库和静态库的区别

加载速度快慢,可扩展性,资源利用率

六 Makefile

好处:自动化编译
普通程序员只需看得懂别人写的,架构师要会写

◼ 文件命名
makefile 或者 Makefile

◼ Makefile 规则
 一个 Makefile 文件中可以有一个或者多个规则
目标 ...: 依赖 ...
命令(Shell 命令)
...

目标:最终要生成的文件(伪目标除外)
 依赖:生成目标所需要的文件或是目标
命令:通过执行命令对依赖操作生成目标(命令前必须 Tab 缩进)

Makefile 中的其它规则一般都是为第一条规则服务的。

◼ 命令在执行之前,需要先检查规则中的依赖是否存在
	 如果存在,执行命令
	 如果不存在,向下检查其它的规则,检查有没有一个规则是用来生成这个依赖的,
	如果找到了,则执行该规则中的命令
	
◼ 检测更新,在执行规则中的命令时,会比较目标和依赖文件的时间
	 如果依赖的时间比目标的时间晚,需要重新生成目标
	 如果依赖的时间比目标的时间早,目标不需要更新,对应规则中的命令不需要被执行

变量

◼ 自定义变量
	变量名=变量值 var=hello     $(var)
◼ 预定义变量
	AR : 归档维护程序的名称,默认值为 ar
	CC : C 编译器的名称,默认值为 cc
	CXX : C++ 编译器的名称,默认值为 g++
	$@ : 目标的完整名称
	$< : 第一个依赖文件的名称
	$^ : 所有的依赖文件
◼ 获取变量的值
	$(变量名)


app:main.c a.c b.c
	gcc -c main.c a.c b.c
#自动变量只能在规则的命令中使用

app:main.c a.c b.c
	$(CC) -c $^ -o $@

模式匹配

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

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

Makefile 的函数

◼ $(wildcard PATTERN...)
	 功能:获取指定目录下指定类型的文件列表
	 参数:PATTERN 指的是某个或多个目录下的对应的某种类型的文件,如果有多
		个目录,一般使用空格间隔
	 返回:得到的若干个文件的文件列表,文件名之间使用空格间隔
	 示例:
		$(wildcard *.c ./sub/*.c)
		返回值格式: a.c b.c c.c d.c e.c f.c


◼ $(patsubst <pattern>,<replacement>,<text>)
 功能:查找<text>中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合
	模式<pattern>,如果匹配的话,则以<replacement>替换。
 <pattern>可以包括通配符`%`,表示任意长度的字串。如果<replacement>
	中也包含`%`,那么,<replacement>中的这个`%`将是<pattern>中的那个%
	所代表的字串。(可以用`\`来转义,以`\%`来表示真实含义的`%`字符)
 返回:函数返回被替换过后的字符串
 示例:
	$(patsubst %.c, %.o, x.c bar.c)
	返回值格式: x.o bar.o

定义伪目标:.PHONY:<目标名> (在Makefile 文件添加)

七 GDB调试

gdb -v //查看gdb版本

编译可执行文件时,加入-g,带入源代码的信息

gcc hello.c -o hello -g   //编译

gdb hello //打开

l //查看代码

b 10 //在代码的第十行添加断点

i b //查看断点的信息

r //运行

n //next. 往下执行

c //continue ,继续运行

一般用g++编译.cpp文件,用gcc编译的话,可能报错(找不到C++的库)

设置断点

调试命令

跳出循环——循环体中的断点设为不可用

八 文件IO

实现跨平台的两种方式

1. Java针对不同的平台开发Java虚拟机

2.标准C库,在不同平台调用系统API 

标准C库的IO函数效率高于Linux系统IO,因为前者带有缓冲区

九 虚拟地址空间

产生背景
1.实际运行的应用程序需要耗费的内存总数 > 计算机内存
2.调度产生的内存碎片造成内存地址空间断裂

程序:磁盘上的代码
进程:磁盘上的代码加载到内存上运行

.

32位的计算机的虚拟地址空间:2的32次方  = 4G个地址
64位:2的48次方

以32位计算机为例

1.高地址的1G为内核区;剩余为用户区
内核区 用户区
普通用户不能操作 栈(小,高到低):
可以通过系统调用操作 堆(大,低到高):
right-aligned 文本居右
2.虚拟地址空间里的数据会被CPU中的内存管理单元(MMU)映射到真实的物理内存上

文件描述符

存在内核区的PCB(进程控制块)中的文件描述符表(1024的数组“前3个默认”)

在这里插入图片描述
同一个文件可以被打开多次,但是文件描述符不一样

man 2 函数名: Linux系统函数API
man 3 函数名:标准C库函数API

open

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>

    //打开一个已经存在的文件
    int open(const char *pathname, int flags);
        -pathname:要打开的文件路径
        -flags:对文件的操作权限设置,还有其他设置
            O_RDONLY,  O_WRONLY,  or  O_RDWR
        -返回值:返回一个新的文件描述符,如果调用失败,返回-1.

    errno:属于Linux系统函数库,库里面的一个全局变量,记录的是最近的错误号

    #include <stdio.h>
    void perror(const char *s);
    作用:打印errno对应的错误描述
        -s:用户描述,比如hello,最终输出: hello:xxx(实际的错误)

    //创建一个新文件
    int open(const char *pathname, int flags, mode_t mode);

create

 #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>

    int open(const char *pathname, int flags, mode_t mode);

        -pathname:要打开的文件路径

        -flags:对文件的操作权限设置,还有其他设置
            必选项:O_RDONLY,  O_WRONLY,  or  O_RDWR (两两互斥)
            可选项:O_CREAT文件不存在则创建

            flags是一个int类型的数据,4B
            32位,每一位代表一种标志位,所以采用按位或可以叠加“可选项”和“必选项”。

        -mode:八进制数,表示用户对新创建文件的操作权限,例如:0775
            最终的权限:mode & ~umask
            umask的作用:抹去某些权限

copy

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

    #include <unistd.h>
    ssize_t write(int fd, const void *buf, size_t count);
        fd:~
        buf:往磁盘写入的数据
        count:写入数据的实际大小
    返回值
        成功:实际写入的字节数
        失败:-1,并设置errno

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);
        fd:文件描述符,open得到,通过fd操作文件
        offset:偏移量
        whence:
            SEEK_SET, 设置文件指针的偏移量
            SEEK_END, 设置偏移量:当前位置+第二个参数offset的值
            SEEK_CUR, 设置偏移量,文件大小+第二个参数offset的值
        函数作用:
            1.移动文件指针到头文件:lseek(fd,0,SEEK_SET);
            2.获取当前文件指针的位置:lseek(fd,0,SEEK_CUR);
            3.获取文件长度:lseek(fd,0,SEEK_END);
            4.拓展文件长度,增加100字节:lseek(fd,100,SEEK_END);
              之后还要写入一次数据拓展才能有效
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
  • 28
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值