Linux系统编程1-Linux系统基础

本文为Linux系统编程自学整理,方便个人随时查看,主要参考黑马程序员[Linux系统编程]

本部分为一些Linux基础知识

Linux系统文件类型

Linux系统文件类型: 7/8 种

文件类型

表示方法

普通文件

-

目录文件

d

字符设备文件

c

块设备文件

b

软连接

l

管道文件

p

套接字

s

未知文件

文件权限

上面图片中是目录项详细信息(ls -l)

从左到右依次为:

文件权限 硬链接计数 所有者 所属组 大小 时间 文件名/文件夹名

权限具体展开:

-rw-rw-r--

1234567890

从左到右:1代表文件类型,234代表所有者读写执行权限,567代表同组用户读写执行权限,890代表其他人读写执行权限

创建修改用户和用户组

whoami 查看当前用户
sudo adduser newusername 添加新用户
chown username filename 修改文件所有者
su username 切换当前用户为username

chomd 修改权限操作

  1. 文字设定法

chmod [who] [+|-|=] [mode] filename

who可以是下述字母中的任一个或者它们的组合

u 表示”用户(user)”,即文件或目录的所有者

g 表示”同组(group)用户”,即与文件所有者有相同组ID的所有用户

o 表示”其他(others)用户”

a 表示”所有(all)用户”,它是系统默认值

操作符号可以是:

+ 添加某个权限

- 取消某个权限

= 赋予给定权限并取消其他所有权限(如果有的话)

如下所示,给file2文件添加执行权限

  1. 数字设定法

chmod 操作码 文件名

对于file2的权限

-rw-rw-r--

421421421

权限都为二进制编号

对此文件设置为如下权限,操作码就是764

所有者 rwx 7

所有者所在组 rw 6

其他用户 r 4

Linux系统目录

目录

存放的东西

bin

存放二进制可执行文件

boot

存放开机启动程序

dev

存放设备文件: 字符设备、块设备

home

存放普通用户

etc

用户信息和系统配置文件 passwd、group

lib

库文件:libc.so.6

root

家目录

usr

用户资源管理目录

其他

ps aux | grep 条件 结果至少有一个,就是当前查询进程
kill 杀死进程
ifconfig 查看网卡信息
man 系统参考手册
man n name 在系统手册第n章查看name

vim基本操作

vim有三种模式:命令模式、文本模式、末行模式

以下均为命令模式下操作:

命令

含义

x

删除光标所在字符,工作模式不变

D

删除光标所在位置到行末,工作模式不变

0(数字)

光标移到行首,工作模式不变

$

光标移到行尾,工作模式不变

d0

删除光标所在位置到行首,工作模式不变

d$

删除光标所在位置到行末,工作模式不变

line-G

行跳转

gg

跳转首行

G

跳转末行

%

光标处于左大括号时,使用%跳转到对应右大括号,再按%跳回去。

其他括号也可以这样

自动缩进

cd /etc/vim
sudo vi vimrc

vimrc 配置文件的底部追加以下命令:

syntax on            //设置语法高亮,一般默认有,可不用添加此句
set tabstop=4           //设置制表符宽度为 4
set softtabstop=4       //设置软制表符宽度为 4
set shiftwidth=4        //设置缩进的空格数为 4
set autoindent          //设置自动缩进
set cindent            //设置使用 c/c++ 语言的自动缩进方式
set nu                //设置在左侧显示行号

删除

命令模式下:

r 替换光标选中字符

v 进入可视模式,选择一片区域按d剪切

dd 剪切光标所在行

n+dd 剪切从光标开始的n行

复制粘贴

yy 复制光标所在行

p 向后粘贴剪切板内容

P 向前粘贴剪切板内容

n-yy 复制光标所在位置的n行,包括光标所在行

查找和替换

查找

/+findname 命令模式下查找

按回车键启动查找后,按n,会自动找下一个,N跳到上一个

查找光标所在单词

光标在目标单词上时,*或者#查找下一个,这里不要求光标必须在首字母上

替换:末行模式下进行

单行替换

光标置于待替换行, :s /待替换词/替换词

全文替换

:%s /待替换词/替换词 默认替换每行的首个,一行有多个目标词时,后面的不会变

:%s /待替换词/替换词/g 真正意义上的全局替换

区域替换

:24,35s/待替换词/替换词/g 替换24-35行之间的目标词

但是有个缺点是:不是替换单词,而是替换相应输入的字母(慎用)

其他

末行模式下

历史命令

Ctrl-p 上一条命令

Ctrl-n 下一条命令

分屏,末行模式下

:sp 水平分屏

:vsp 竖直分屏

分屏命令+filename,分屏并打开这个文件

分屏后屏幕切换,Ctrl-w-w

使用:q退出光标所在窗口

使用:qall退出所有窗口

命令模式下

u 撤销操作

Ctrl-r 反撤销

从vim中跳转manpage

将光标放在待查看单词上,按K,默认看第一卷

n+K,查看第n卷

查看宏定义

光标放在待查看词上,[+d即可查看

gcc编译

编译四步骤

gc编译可以执行程序 4步骤:预处理、编译、汇编、链接

地址回填和数据段合并(链接阶段)

链接阶段会做地址回填:将链接后的main的地址填入

地址回填:写在源代码里的函数,相对main函数偏移是一定的,链接时,回填main函数地址之后,其他源代码里的函数也就得到了地址。

Fun1()和fun2()都是自己写的函数

数据段合并:节省空间

32位操作系统

0-4G

32位操作系统一个a.out文件会有0-4g的地址空间

.text是代码段(只读);.rodata:只读数据段;.data:数据段;

.data和.bss的区别是一个是未初始化的,一个是初始化为非零

Heap:堆;stack:栈

堆是从低地址到高地址;栈是从高地址到低地址。两者中间的位置越来越小。

动态库内存加载位置就是在堆和栈之间

环境变量和main函数的参数在栈的上方--导致动态库环境变量失效原因

系统调用可以完成从用户区到内核区的切换

数据段合并(节省空间)

不进行合并的话,若.rodata使用4b,.text使用1kb,但使用内存一次最少用4kb(使用磁盘存储使用512)

text和rodata都为可读,合并为一个

.data和.bss都为可读可写,合并为一个,

内存中其实有很多个段,数据段合并不止是这几个段进行合并

编译常用参数

-I 指定头文件所在目录位置

gcc -I ./hellodir hello.c -o hello(其中头文件hello.h在文件夹hellodir中)

-c 只做预处理,编译,汇编。得到二进制文件

-g 编译时添加调试文件,用于gdb调试

-Wall 显示所有警告信息

-D 向程序中“动态”注册宏定义

-l 指定动态库库名

-L 指定动态库路径

动态库和静态库

静态库在文件中静态展开,所以有多少文件就展开多少次,非常吃内存,100M展开100次,就是1G,但是这样的好处就是静态加载的速度快

使用动态库会将动态库加载到内存,10个文件也只需要加载一次,然后这些文件用到库的时候临时去加载,速度慢一些,但是很省内存

动态库和静态库各有优劣,根据实际情况合理选用即可。但由于计算机的发展,速度可忽略了,使用动态库更多

静态库

静态库名字以lib开头,以.a结尾

例如:libmylib.a

静态库生成指令

ar rcs libmylib.a file1.o

制作和使用

隐式声明: 万恶之源:C语言中的隐式函数声明_smstong的博客-CSDN博客_c语言函数隐式声明

制作一个包含加法、除法、减法的动态库;指定头文件位置;使用头文件守卫

  1. 源代码

test.c为主函数;add.c、sub.c、div.c为调用函数

  1 # include<stdio.h>
  2 # include<stdlib.h>
  3 # include<string.h>
  4 # include<unistd.h>
  5 # include<pthread.h>
  6 
  7 int add(int, int);
  8 int sub(int, int);  //可做成头文件,后面有介绍
  9 int div1(int, int);
 10 
 11 int main() {
 12     int a = 15;
 13     int b = 5;
 14     printf("%d - %d = %d\n",a,b,sub(a,b));
 15     printf("%d / %d = %d\n",a,b,div1(a,b));
 16     printf("%d + %d = %d\n",a,b,add(a,b));
 17     return 0;
 18 }
  1 int div1(int a, int b){
  2     return a / b;
  3 }
  1 int sub(int a,int b){
  2      return a-b;
  3 }
  1 int add(int a,int b){
  2     return a+b;
  3 }
  1. 编译生成.o文件

gcc -c add.c -o add.o
gcc -c sub.c -o sub.o
gcc -c div.c -o div1.o
  1. 制作静态库(其中test.c在当前cppcode目录,.o文件在staticlib目录)

ar rcs libmymath.a add.o sub.o div1.o
  1 # include<stdio.h>
  2 # include<stdlib.h>
  3 # include<string.h>
  4 # include<unistd.h>
  5 # include<pthread.h>
  6 # include"mymath.h"
  7 
  8 int main() {
  9     int a = 15;
 10     int b = 5;
 11     printf("%d - %d = %d\n",a,b,sub(a,b));
 12     printf("%d / %d = %d\n",a,b,div1(a,b));
 13     printf("%d + %d = %d\n",a,b,add(a,b));
 14     return 0;
 15 }

在INC目录下创建mymath.h

  1 #ifndef _MYMATH_H_
  2 #define _MYMATH_H_
  3 
  4 int add(int,int);
  5 int sub(int,int);
  6 int div1(int,int);
  7 
  8 #endif
gcc test.c ./staticlib/libmymath.a -o a.out -I ./INC
./a.out

15 - 5 = 10

15 / 5 = 3

15 + 5 = 20

动态库

没有调用到动态库内部的函数的时候,动态库不会加载使用;只有调用到动态库的内部的函数的时候,动态库才会被加载到内存,同时绑定地址;

动态库要求生成与位置无关的代码(函数调用之前需要将其地址固定)

动态库里的函数在地址回填时与自己制作的函数不同,会用一个@plt来标识,当动态库加载到内存时,再用加载进去的地址将@plt替换掉。

制作

  1. 生成位置无关的.o文件

gcc -c add.c -o add.o -fPIC

使用这个参数过后,生成的函数就和位置无关,挂上@plt标识,等待动态绑定

使用gcc -shared制作动态库

gcc -shared -o lib库名.so add.o sub.o div.o

编译可执行程序时指定所使用的动态库。-l:指定库名 -L:指定库路径

gcc test.c -o a.out -l mymath -L ./lib -I ./INC

  1. 运行可执行程序./a.out

此时直接执行4会出错,因为要提供动态库所在目录位置

解决方式:

【1】 通过环境变量: export LD_LIBRARY_PATH=动态库路径

./a.out 成功!!! (临时生效, 终端重启环境变量失效)

失效的原因是 一个程序会生成一个地址空间,环境变量也在这个空间中,一旦终端关闭,程序失效,地址空间也没了

【2】 永久生效: 写入 终端配置文件。 .bashrc 建议使用绝对路径。

1) vi ~/.bashrc

2) 写入 export LD_LIBRARY_PATH=动态库路径 保存

3). .bashrc/ source .bashrc / 重启终端 ---> 让修改后的.bashrc生效

4)./a.out 成功!!!

【3】 拷贝自定义动态库 到 /lib(标准C库所在目录位置)

【4】 配置文件法

  1. sudo vi /etc/ld.so.conf

2) 写入 动态库绝对路径 保存

  1. sudo ldconfig -v 使配置文件生效。

4)./a.out 成功!!!--- 使用ldd a.out 查看

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值