• 《Unix/Linux系统编程》学习笔记1


    第1章 引言

    一.知识点归纳

    1.Unix的历史

    Unix是一种通用操作系统。该系统诞生于20世纪70年代早期,由肯·汤普森和丹尼斯·里奇采用贝尔实验室的PDP-11微型计算机开发。1975年,贝尔实验室向公众发布了Unix,称为V6 Unix。

    2.Linux的历史

    Linux是一个类Unix系统。它最初是林纳斯·托瓦斯在1991年为基于INtel x86的个人计算机开发的一个实验室内核。后来,世界各地的人都开始加入Linux的研发队伍。在20世纪90年代末,Linux与GNU相结合,纳入了许多GNU软件,极大地促进了Linux的进一步发展。不久之后,Linux实现了访问互联网的TCP/IP协议族,并移植了支持GUI的X11,成为一个完整的操作系统。

    3.本书目标

    1. 强化学生的编程背景知识
    2. 动态数据结构的应用
    3. 进程概念和进程管理
    4. 并发编程
    5. 定时器和定时功能
    6. 信号、信号处理和进程间通信
    7. 文件系统
    8. TCP/IP和网络编程

    4.Unix/Linux命令

    • ls:ls dirname:列出CWD或目录的内容。
    • cd dirname:更改目录。
    • pwd:打印CWD的绝对路径名。
    • touch filename:更改文件名时间戳(如果文件不存在,则创建文件)。
    • cat filename:显示文件内容。
    • cp src dest:复制文件。
    • mv src dest:移动或重命名文件。
    • mkdir dirname:创建目录。
    • rmdir dirname:移除(空)目录。
    • rm filename:移除或删除文件。
    • ln oldfile newfile:在文件之间创建链接。
    • find:搜索文件。
    • grep:搜索文件中包含模式的行。
    • ssh:登录到远程主机。
    • gzip filename:将文件压缩为.gz文件。
    • gunzip file.gz:解压.gz文件。
    • tar -zcvf file.tgz .:从当前目录创建tar文件。
    • tar -zxvf file.tgz .:从.tgz文件中解压文件。
    • man:显示在线手册页。
    • zip file.zip filenames:将文件压缩为.zip文件。
    • unzip file.zip:解压.zip文件。

    5.一些常用快捷键

    • Ctrl+c:强行终止当前程序
    • Ctrl+d:键盘输入结束或退出终端
    • Ctrl+s:暂停当前程序,暂停后按下任意键恢复运行
    • Ctrl+z:将当前程序放到后台运行,恢复到前台为命令fg
    • Ctrl+a:将光标移至输入行头,相当于Home键
    • Ctrl+e:将光标移至输入行末,相当于End键
    • Ctrl+k:删除从光标所在位置到行末
    • Alt+Backspace:向前删除一个单词
    • Shift+PgUp:将终端显示向上滚动
    • Shift+PgDn:将终端显示向下滚动

    6.Linux 的目录结构

    image

    7.课上用过的Linux命令

    二.问题与解决思路

    1.网络无法连接

    • 还原默认设置
    • 使用nmcli,在命令端输入:

    sudo nmcli networking off
    sudo nmcli networking on

    再重启网络:

    sudo service network-manager restart

    三.实践内容与截图

    1.用户及文件权限管理

    (1)查看用户:

    who am i
    或者
    who mom likes

    有一点需要注意的是,在某些环境中 who am i 和 who mom likes 命令不会输出任何内容,这是因为当前使用的 Shell 不是登录式 Shell(login shell),没有用户与 who 的 stdin 相关联,因此不会输出任何内容。登录 Shell 是指用户使用自己的 user ID 登录交互式 shell 的第一个进程,判断是不是登录 Shell 可以执行 echo $0 命令,如果返回 zsh、/bin/zsh、/bin/bash 这种格式,说明是非登录式 Shell(non-login shell);如果返回 -zsh、-bash 则说明是登录式 Shell,这时你执行 who am i 就会有输出。
    image

    (2)创建用户:

    现在我们新建一个叫 lilei 的用户:
    image
    这个命令不但可以添加用户到系统,同时也会默认为新用户在/home目录下创建一个工作目录:
    image
    现在已经创建好一个用户,并且可以使用创建的用户登录,使用如下命令切换登录用户:
    image

    (3)用户组:

    在 Linux 里面如何知道自己属于哪些用户组呢?
    方法一:使用 groups 命令
    image
    方法二:查看 /etc/group 文件
    在最下面看到 shiyanlou 的用户组信息
    image
    也可以使用 grep 命令过滤掉一些不想看到的结果
    image
    将其它用户加入 sudo 用户组:
    image

    (4)删除用户和用户组:

    删除用户:
    image
    删除用户组可以使用 groupdel 命令,倘若该群组中仍包括某些用户,则必须先删除这些用户后,才能删除群组。

    (5)查看文件权限:

    image
    image
    image

    • 显示所有文件大小,并以普通人类能看懂的方式呈现:
      image

    (6)变更文件所有者:

    切换到 lilei 用户,然后在 /home/lilei 目录新建一个文件,命名为 iphone11。
    image
    此时可见文件所有者是lilei。
    现在切换回到ycy用户,使用以下命令变更文件所有者为ycy。
    image

    (7)修改文件权限:

    • 方式一:二进制数字表示
      image
      每个文件有三组固定的权限,分别对应拥有者,所属用户组,其他用户,记住这个顺序是固定的。文件的读写执行对应字母 rwx,以二进制表示就是 111,用十进制表示就是 7,对进制转换不熟悉的同学可以看看 进制转换。例如我们刚刚新建的文件 iphone11 的权限是 rw-rw-rw-,换成对应的十进制表示就是 666,这就表示这个文件的拥有者,所属用户组和其他用户具有读写权限,不具有执行权限。
      如果我要将文件 iphone11 的权限改为只有我自己可以用那么就可以用这个方法更改它的权限。
    • 方式二:加减赋值操作
      image
      g、o还有u分别表示group(用户组)、others(其他用户)和user(用户),+和-分别表示增加和去掉相应的权限。

    2.Linux 目录结构及文件基本操作

    (1)新建:

    • 新建空白文件
      创建名为test的空白文件,因为在其它目录没有权限,所以需要先cd~切换回用户的Home目录:

    cd ~
    touch test

    • 新建目录
      创建名为“mydir”的空目录:

    mkdir mydir

    使用 -p 参数,同时创建父目录(如果不存在该父目录),如下我们同时创建一个多级目录(这在安装软件、配置安装路径时非常有用):

    mkdir -p father/son/grandson

    (2)复制:

    • 复制文件
      将之前创建的 test 文件复制到 /home/shiyanlou/father/son/grandson 目录中:

    cp test father/son/grandson

    • 复制目录
      要成功复制目录需要加上 -r 或者 -R 参数,表示递归复制:

    cd /home/ycy
    mkdir family
    cp -r father family

    (3)删除:

    • 删除文件
      使用rm命令删除一个文件:

    rm test

    有时候你会遇到想要删除一些为只读权限的文件,直接使用 rm 删除会显示一个提示,你如果想忽略这提示,直接删除文件,可以使用 -f 参数强制删除:

    rm -f test

    • 删除目录
      跟复制目录一样,要删除一个目录,也需要加上 -r 或 -R 参数:

    rm -r family

    遇到权限不足删除不了的目录也可以和删除文件一样加上 -f 参数:

    rm -rf family

    (4)移动文件与文件重命名:

    • 移动文件
      使用mv命令移动文件(剪切)。命令格式是 mv 源目录文件 目的目录
      例如将文件“file1”移动到 Documents 目录:
      image
    • 重命名文件
      mv命令除了能移动文件外,还能给文件重命名。命令格式为 mv 旧的文件名 新的文件名
      例如将文件“file1”重命名为“myfile”:
      image
    • 批量重命名

    cd /home/shiyanlou/
    使用通配符批量创建 5 个文件:
    touch file{1..5}.txt
    批量将这 5 个后缀为 .txt 的文本文件重命名为以 .c 为后缀的文件:
    rename 's/.txt/.c/' *.txt
    批量将这 5 个文件,文件名和后缀改为大写:
    rename 'y/a-z/A-Z/' *.c

    (5)查看文件:

    • 使用 cat,tac 和 nl 命令查看文件
      前两个命令都是用来打印文件内容到标准输出(终端),其中 cat 为正序显示,tac 为倒序显示。
      image
      可以加上 -n 参数显示行号:
      image
    • 使用 more 和 less 命令分页查看文件
      image
      打开后默认只显示一屏内容,终端底部显示当前阅读的进度。可以使用 Enter 键向下滚动一行,使用 Space 键向下滚动一屏,按下 h 显示帮助,q 退出。
    • 使用 head 和 tail 命令查看文件
      只查看文件的头几行(默认为 10 行,不足 10 行则显示全部)和尾几行。
      image
      甚至更直接的只看一行, 加上 -n 参数,后面紧跟行数:
      image

    (6)查看文件类型:

    使用 file 命令查看文件的类型:
    image

    (7)编辑文件:

    在Linux中编辑文件通常我们会直接使用专门的命令行编辑器比如(emacs,vim,nano),详见第二章

    vimtutor


    第2章 编程背景

    一.知识点归纳

    1.Linux中的文本编辑器

    (1)vim:

    • 普通模式:按a键或者i键进入插入模式。
    • 插入模式:可以按ESC键回到普通模式。
    • 命令行模式:在命令行模式中可以输入会被解释成并执行的文本。例如执行命令(:键),搜索(/和?键)或者过滤命令(!键)。
    1. 命令行模式下保存文档:从普通模式输入:进入命令行模式,输入w回车,保存文档。
    2. 命令行模式下退出vim:从普通模式输入:进入命令行模式,输入wq回车,保存并退出编辑。
      image

    (2)gedit

    (3)emacs:可输入apt-get install emacs进行安装

    image

    • 详细操作见 “ 三.实践内容与截图 ”。

    2.C语言数据结构

    二.问题与解决思路

    1.安装时无法定位软件包

    image
    打开系统设置——软件和更新——ubuntu软件,把源选择清华大学的(mirrors.tuna.tsinghua.edu.cn),最后更新一下就可以了。

    2.在Linux中,C语言调用汇编代码怎样运行?

    3.在Linux中,汇编代码调用C语言怎样运行?

    4.编译出现-invalid instruction suffix for push

    image

    • 错误原因:在64位系统和32位系统的as命令对于某些汇编指令的处理支持不一样造成的。在.s文件中,包含指令:pushl %ebp,该指令在64位系统下就编译不过。
    • 解决方法:在.s文件中,在代码头部添加 .code32 即可。
      image

    5.段错误(核心已转储)

    image

    1. 内存访问出错
      这类问题的典型代表就是数组越界。
    2. 非法内存访问
      出现这类问题主要是程序试图访问内核段内存而产生的错误。
    3. 栈溢出
      Linux默认给一个进程分配的栈空间大小为8M。c++申请变量时,new操作申请的变量在堆中,其他变量一般在存储在栈中。 因此如果你数组开的过大变会出现这种问题。

    三.实践内容与截图

    1. 程序开发(使用教材上代码2.3.1

    • 程序开发步骤

    (1)创建源文件:

    使用文本编辑器(gedit或emacs)创建一个或多个程序源文件。在系统编程中,最重要的编程语言是C语言和汇编语言。
    image

    (2)用gcc把源文件转换成二进制可执行文件:

    image

    (3)gcc是一个程序,它包含三个主要步骤:

    1. 将C源文件转换为汇编语言文件。 (.c 文件 -> .s 文件)
    2. 把汇编代码转换成目标代码。 (.s 文件 -> .o 文件)
    3. 链接。 (所有 .o 文件 -> a.out 文件)
    • a.out文件包含以下部分:
    1. 文件头:文件头包含a.out文件的加载信息和大小,其中
      • tsize = 代码段大小
      • dsize = 包含初始化全局变量和初始化静态局部变量的数据段的大小
      • bsize = 包含未初始化全局变量和未初始化静态局部变量的bss段的大小
      • total_size = 加载的 a.out 文件的总大小
    2. 代码段:也称正文段,其包含程序的可执行代码。代码段从标准C启动代码 crt0.o 开始,该代码调用main()函数。
    3. 数据段:数据段包含初始化全局变量和初始化静态变量。
    4. 符号表:可选,仅为运行调试所需。
    • 程序执行过程

    在类Unix操作系统中,在sh命令行 a.out one two three 执行 a.out 文件。
    image

    2. 64位GCC中的运行时堆栈使用情况(使用教材上代码2.4.3

    (1)t.c文件中包含一个main()函数,调用一个sub()函数:

    image

    (2)在64位Linux中,编译 t.c 生成64位汇编的 t.s 文件:

    image
    然后,编辑 t.s 文件,删除编译器生成的非必要行,并添加注释来解释代码操作,如下:

    点击查看代码
    #====== t.s file generated by 64-bit GCC compiler ======
    	.globl	sub
    sub:		   # int sub(int a,b,c,d,e,f,g,h)
    
    # first 6 parameters a,b,c,d,e,f are in registers
    #			rdi,rsl,rdx,rcx,r8d,r9d
    # 2 extra parameters g,h are on stack.
    # Upon entry, stack top contains g,h
    #   ------------------------------------
    #   ... ...| h | g | PC |    LOW address
    #   -----------------|------------------
    #			rsp
    # establish stack frame	
    	pushq	%rbp
    	movq	%rsp, %rbp
    # no need to shift rsp down because each function has a 128 bytes
    # reserved stack area.
    # rsp will be shifted down if function define more locals
    
    # save first 6 parameters in registers on stack
    	movl	%edi, -20(%rbp)	# a
    	movl	%esi, -24(%rbp)	# b
    	movl	%edx, -28(%rbp)	# c
    	movl	%ecx, -32(%rbp)	# d
    	movl	%r8d, -36(%rbp)	# e
    	movl	%r9d, -40(%rbp)	# f
    	
    # access locals u,v,w at rbp -4 to -12
    	movl	$9, -12(%rbp)
    	movl	$10, -8(%rbp)
    	movl	$11, -4(%rbp)
    	
    # compute x+g+u+v:
    	movl	-20(%rbp), %edx
    	movl	16(%rbp), %eax
    	addl	%eax, %edx
    	movl	-12(%rbp), %eax
    	addl	%eax, %edx
    	movl	-8(%rbp), %eax
    	addl	%edx, %eax
    	
    # did not shift  rsp down , so just pspQ to restore rbp
    	popq	%rbp
    	ret
    	
    #====== main function code in assembly ======
    	.globl	main
    	.type	main, @function
    main:
    # establish stack frame	
    	pushq	%rbp
    	movq	%rsp, %rbp
    	
    # shift rsp down 48 bytes for locals
    	subq	$48, %rsp
    	
    # locals are at rbp -4 to -32
    	movl	$1, -36(%rbp)	# a = 1
    	movl	$2, -32(%rbp)	# b = 2
    	movl	$3, -28(%rbp)	# c = 3
    	movl	$4, -24(%rbp)	# d = 4
    	movl	$5, -20(%rbp)	# e = 5
    	movl	$6, -16(%rbp)	# f = 6
    	movl	$7, -12(%rbp)	# g = 7
    	movl	$8, -8(%rbp)	# h = 8
    	
    # call sub(a,b,c,d,e,f,g,h): first 6 parameters in registers
    	movl	-16(%rbp), %r9d	# f in r9
    	movl	-20(%rbp), %r8d # e in r8
    	movl	-24(%rbp), %ecx # d in ecx
    	movl	-28(%rbp), %edx # c in edx
    	movl	-32(%rbp), %esi # b in esi
    	movl	-36(%rbp), %eax # a in eax but will be in edi
    	
    # push 2 extra parameters h,g on stack
    	movl	-8(%rbp), %edi	# int h in edi
    	pushq	%rdi		#pushQ rdi ; only low 32-bits = h
    	movl	-12(%rbp), %edi	# int g in edi
    	pushq	%rdi		#pushQ rdi ; low 32-bits = g
    	
    	movl	%eax, %edi	# parameter a in edi
    	call	sub		# call sub(a,b,c,d,e,f,g,h)
    	
    	addq	$16, %rsp	# pop stack: h,g, 16 bytes
    	movl	%eax, -4(%rbp)	# i=sub return value in eax
    	
    	movl	$0, %eax	#return 0 to crt0.o
    	leave
    	ret
    
    # GCC compiler version 11.2.0
    	.ident	"GCC: (Ubuntu 11.2.0-19ubuntu1) 11.2.0"
    

    image
    image

    3. C语言程序与汇编代码的链接

    (1)用汇编代码编程(使用教材上代码2.5.1 ):

    image

    cc -m32 -S a.c ==> a.s file
    gcc -E name.c -o name.i 预编译过程,从.c到.i;
    gcc -S name.i -o name.s 编译,将预处理的C代码转化为汇编码;
    gcc -C name.s -o name.o 转换为机器码

    image

    image

    (2)用汇编语言实现函数(使用教材上代码2.5.2 ):

    <1>示例2.3:

    image
    image

    <2>示例2.4:

    image

    3.Makefile

    (1)make程序(使用教材上代码2.7.2 ,书上代码有错误!!!):

    image

    image

    image

    (2)makefile示例:

    1. 创建一个名为mkl的makefile,包括:
      image
    2. 使用mkl作为makefile运行make:
      image
    3. 再次运行make命令,会显示: “myt”已是最新
    4. 相反,如果依赖项列表中的任何文件有更改,make将再次执行rule命令。

    (3)makefile中的宏:

    1. 创建一个叫mk2的makefile,包括:
      image
    2. 以mk2作为makefile运行make:
      image
    3. 按前面一样运行生成的二进制可执行文件myt

    4.链接库(参考:https://blog.csdn.net/wohu1104/article/details/110789570

    • 创建4个文件:

    image

    image

    (1)静态链接库:

    • 创建静态链接库
    1. 将所有指定的源文件,都编译成相应的目标文件

    gcc -c greeting.c name.c

    1. 然后使用 ar 压缩指令,将生成的目标文件打包成静态链接库,其基本格式如下:

    ar rcs 静态链接库名称 目标文件1 目标文件2 ...

    重点说明的是,静态链接库的不能随意起名,需遵循如下的命名规则:

    libxxx.a

    Linux 系统下,静态链接库的后缀名为 .a
    Windows 系统下,静态链接库的后缀名为 .lib

    ar rcs libmyfunction.a greeting.o name.o

    • 使用静态链接库
    1. 首先我们将 main.cpp 文件编译为目标文件:

    gcc -c main.c

    1. 在此基础上,我们可以直接执行如下命令,即可完成链接操作:

    gcc -static main.o -L. -lmyfunction

    1. 由此,就生成了 a.out 可执行文件:

    ./a.out

    image

    (2)动态链接库:

    • 创建动态链接库
    1. 直接使用源文件创建动态链接库,采用 gcc 命令实现的基本格式如下:

    gcc -fpic -shared 源文件名... -o 动态链接库名

    其中,

    • shared 选项用于生成动态链接库;
    • fpic(还可写成 -fPIC)选项的功能是,令 GCC 编译器生成动态链接库(多个目标文件的压缩包)时,表示各目标文件中函数、类等功能模块的地址使用相对地址,而非绝对地址。这样,无论将来链接库被加载到内存的什么位置,都可以正常使用。

    例如,将前面项目中的 greeting.c 、name.c 这 2 个源文件生成一个动态链接库,执行命令为:

    gcc -FPIC -shared greeting.c name.c -o libmyfunction.so

    1. 先使用 gcc -c 指令将指定源文件编译为目标文件,再由目标文件生成动态链接库

    gcc -c -FPIC greeting.c name.c

    在此基础上,接下来利用上一步生成的目标文件,生成动态链接库:

    gcc -shared greeting.o name.o -o libmyfunction.so

    • 使用动态链接库
      执行如下指令,即可借助动态链接库成功生成可执行文件:

    gcc main.c libmyfunction.so -o main

    注意,生成的可执行文件 main 通常无法直接执行,例如:
    image
    运行由动态链接库生成的可执行文件时,必须确保程序在运行时可以找到这个动态链接库。常用的解决方案有如下几种:

    1. 将链接库文件移动到标准库目录下(例如 /usr/lib、/usr/lib64、/lib、/lib64);
    2. 在终端输入:

    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:xxx

    其中 xxx 为动态链接库文件的绝对存储路径(此方式仅在当前终端有效,关闭终端后无效);
    3. 修改 ~/.bashrc 或 ~/.bash_profile 文件,即在文件最后一行添加:

    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:xxx

    其中 xxx 为动态链接库文件的绝对存储路径,保存之后,执行 source bashrc 指令(此方式仅对当前登陆用户有效)。

    在本示例中采用第二种方案,即在终端输入

    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/ycy

    即可使 main 成功执行。
    image

  • 相关阅读:
    21 viewPager--- hzScrollView ----llContainer
    21 ViewPager RadioGroup
    CLEAR REFRESH FEEE的区别
    在ALV中更新数据库表
    cl_gui_cfw=>flush
    cl_gui_cfw=>dispatch
    数据库表-DD01L DD02L DD03L-保存数据表和域的消息
    SAP 锁机制
    ABAP 搜索帮助
    SAP Basis常用事务代码
  • 原文地址:https://www.cnblogs.com/20201212ycy/p/16652139.html
Copyright © 2020-2023  润新知