【Linux操作系统】探秘Linux奥秘:Linux开发工具的解密与实战

简介: 【Linux操作系统】探秘Linux奥秘:Linux开发工具的解密与实战



🪐1 初识Linux OS

Linux是一种开源的Unix-like操作系统内核,它是基于POSIX和Unix的多用户、多任务、支持多线程和多CPU的操作系统。Linux内核最初是由芬兰程序员Linus Torvalds在1991年创建的,之后成为自由软件和开源社区的一个主要项目。

以下是Linux操作系统的一些主要特点和组成部分:

  1. 内核(Kernel): Linux内核是操作系统的核心,它管理系统资源,如处理器、内存、设备驱动程序等。Linus Torvalds最初编写了Linux内核,它是Linux操作系统的基础。
  2. Shell(命令解释器): Linux操作系统使用命令行界面(CLI),用户与系统交互通过Shell。用户可以通过输入命令执行各种任务,管理文件、进程、权限等。常见的Shell包括Bash(Bourne Again SHell)和Zsh。
  3. 文件系统: Linux支持多种文件系统,包括Ext4、XFS、Btrfs等。文件系统负责管理存储设备上的文件和目录,以及文件的权限、所有权等信息。
  4. 用户界面: 虽然Linux以CLI为主,但也支持图形用户界面(GUI)。常见的Linux桌面环境有GNOME、KDE、XFCE等,它们提供了直观的用户体验。
  5. 软件包管理系统: 大多数Linux发行版都有自己的软件包管理系统,用于安装、更新和删除软件。常见的包管理工具有APT(Debian/Ubuntu)、YUM(Red Hat/CentOS)、Pacman(Arch Linux)等。
  6. 网络功能: Linux具有强大的网络功能,支持各种网络协议和服务。它可以作为服务器运行各种网络服务,如Web服务器(Apache、Nginx)、邮件服务器(Postfix、Sendmail)、文件服务器(Samba)等。
  7. 多用户和多任务: Linux是一个多用户系统,多个用户可以同时访问同一台机器。它也是一个多任务系统,可以同时运行多个进程。
  8. 安全性: Linux以安全性而闻名,系统管理员可以设置用户权限、访问控制列表(ACLs)等来确保系统的安全性。
  9. 开源和自由: Linux是开源软件,其源代码可以被任何人查看、修改和分发。大多数Linux发行版是免费提供的,用户可以自由选择、使用和分发。
  10. 发行版(Distribution): 由于Linux内核是开源的,不同的组织和社区创建了各种Linux发行版,例如Ubuntu、Debian、Fedora、CentOS、Arch Linux等。每个发行版都有自己的特点和包管理系统。

总体而言,Linux操作系统是一个强大、灵活且可定制的操作系统,广泛应用于服务器、嵌入式系统、超级计算机等各种领域。


🪐2 Linux开发工具的解密与实战

🌍1. 实验目的

  • 掌握gcc编译方法与使用;
  • 掌握Linux调试器GDB的使用;
  • 实践编译与调试技能,提升对软件开发环境的熟练度。

🌍2. 实验准备

  • 获取 Linux 镜 像文件:下载适用于虚拟机的 Linux 镜像文件,比如 Ubuntu 21.04,从 Ubuntu 官方网站 获取。
  • 安装虚拟化软件:安装 VMware Workstation 或 Virtualbox,两者提供简便的虚拟机管理和配置。
  • 创建 Linux 虚拟机:打开虚拟化软件,按照指引创建新虚拟机。设置内存为 2GB 或更多,其余选项选择 默认值。加载下载好的 Linux 系统 ISO 镜像文件,启动虚拟机完成 Linux 系统安装。

🌍3. 实验内容

1.编译器gcc的使用

(1)编辑一个C语言程序文件 hello.c ,代码如下:

#include <stdio.h>
main()
{
    char name[20];
    printf(“Please input your name :”);
    scanf(“% s”, name);
    printf(“Welcome % s !\n”, name);
    return 0;
}

(2)编译文件: gcc -o hello hello.c。

(3)若有错误,修改hello.c的内容,然后再次编译,直至没有错误为止。

解:

(1)编辑一个C语言程序文件 hello.c ,代码如下:

#include <stdio.h>
main()
{
    char name[20];
    printf(“Please input your name :”);
    scanf(“% s”, name);
    printf(“Welcome % s !\n”, name);
    return 0;
}

在终端输入vim hello.c,将示例代码输入到hello.c结果显示如下:

退出保存,文件夹多了hello.c文件夹

(2)编译文件: gcc -o hello hello.c。

(3)若有错误,修改hello.c的内容,然后再次编译,直至没有错误为止。

在终端输入gcc -o hello hello.c结果显示报错如下所示:

回到源码hello.c,我们根据报错信息分段分析。

第一段:

hello.c:2:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
    2 | main()
      | ^~~~
hello.c: In function ‘main’:
hello.c:5:10: error: stray ‘\342’ in program
    5 |   printf(���Please input your name:”);
      |          ^
hello.c:5:11: error: stray ‘\200’ in program
    5 |   printf(���Please input your name:”);
      |           ^
hello.c:5:12: error: stray ‘\234’ in program
    5 |   printf(��Please input your name:”);
      |            ^
hello.c:5:13: error: ‘Please’ undeclared (first use in this function)
    5 |   printf(“Please input your name:”);
      |             ^~~~~~
hello.c:5:13: note: each undeclared identifier is reported only once for each function it appears in
hello.c:5:19: error: expected ‘)’ before ‘input’
    5 |   printf(“Please input your name:”);
      |                   ^~~~~~
      |                   )
hello.c:5:36: error: stray ‘\342’ in program
    5 |   printf(“Please input your name:���);
      |                                    ^
hello.c:5:37: error: stray ‘\200’ in program
    5 |   printf(“Please input your name:���);
      |                                     ^
hello.c:5:38: error: stray ‘\235’ in program
    5 |   printf(“Please input your name:��);

这一段显示源码的错误提示是因为代码中使用了不可见的特殊字符,导致编译器无法识别。可以很容易发现源码中的printf(“Please input your name:”);的双引号使用的是中文模式输入,故将其改成printf("Please input your name:");

第二段:

hello.c:6:9: error: stray ‘\342’ in program
    6 |   scanf(���%s”,name);
      |         ^
hello.c:6:10: error: stray ‘\200’ in program
    6 |   scanf(���%s”,name);
      |          ^
hello.c:6:11: error: stray ‘\234’ in program
    6 |   scanf(��%s”,name);
      |           ^
hello.c:6:12: error: expected expression before ‘%’ token
    6 |   scanf(“%s”,name);
      |            ^
hello.c:6:14: error: stray ‘\342’ in program
    6 |   scanf(“%s���,name);
      |              ^
hello.c:6:15: error: stray ‘\200’ in program
    6 |   scanf(“%s���,name);
      |               ^
hello.c:6:16: error: stray ‘\235’ in program
    6 |   scanf(“%s��,name);
      |                ^

这一段显示源码的错误提示仍然是因为代码中使用了不可见的特殊字符,导致编译器无法识别。可以很容易发现源码中的scanf(“%s”,name);的双引号使用的是中文模式输入,故将其改成scanf("%s",name);

第三段:

hello.c:7:10: error: stray ‘\342’ in program
    7 |   printf(���Welcome %s!\n”,name);
      |          ^
hello.c:7:11: error: stray ‘\200’ in program
    7 |   printf(���Welcome %s!\n”,name);
      |           ^
hello.c:7:12: error: stray ‘\234’ in program
    7 |   printf(��Welcome %s!\n”,name);
      |            ^
hello.c:7:13: error: ‘Welcome’ undeclared (first use in this function)
    7 |   printf(“Welcome %s!\n”,name);
      |             ^~~~~~~
hello.c:7:22: error: ‘s’ undeclared (first use in this function)
    7 |   printf(“Welcome %s!\n”,name);
      |                      ^
hello.c:7:23: error: expected ‘)’ before ‘!’ token
    7 |   printf(“Welcome %s!\n”,name);
      |                       ^
      |                       )
hello.c:7:24: error: stray ‘\’ in program
    7 |   printf(“Welcome %s!\n”,name);
      |                        ^
hello.c:7:26: error: stray ‘\342’ in program
    7 |   printf(“Welcome %s!\n���,name);
      |                          ^
hello.c:7:27: error: stray ‘\200’ in program
    7 |   printf(“Welcome %s!\n���,name);
      |                           ^
hello.c:7:28: error: stray ‘\235’ in program
    7 |   printf(“Welcome %s!\n��,name);

这一段显示源码的错误提示仍然是因为代码中使用了不可见的特殊字符,导致编译器无法识别。可以很容易发现源码中的printf(“Welcome %s!\n”,name);的双引号使用的是中文模式输入,故将其改成printf("Welcome %s!\n",name);

此时改后的代码为:

此时进行编译报错如下:

提示错误是由于没有定义main()的类型,故将main函数前加上int,最终修改版代码如下:

再次进行编译结果显示通过如下:

   

输入./hello运行结果如下:

 

2.使用GDB 调试程序BUG(教材12.7节)

(1)使用文本编辑器输入以下代码greet.c。程序试图倒序输出main 函数中定义的字符串,但结果没有显示。

#include <stdio.h>
int display1(char *string);
int display2(char *string);
main()
{
    char string[] = “Welcome to Linux !”;
    display1(string);
    display2(string);
}
int display1(char *string)
{
    printf(“The original string is % s \n”, string);
}
int display2(char *string1)
{
    char *string2;
    int size, i;
    size = strlen(string1);
    string2 = (char *)malloc(size + 1);
    for (i = 0; i < size; i++)
    {
        string2[size - i] = string1[i];
    }
    string2[size + 1] =’’;
    printf(“The string afterward is % s\n”, string2);
}

(2)使用gcc –g 的选项编译这段代码,运行生成的可执行文件,观察运行结果。

(3)使用gdb 调试程序,通过设置断点、单步跟踪,一步步找出错误所在。(调试过程需截图)

(4)纠正错误,更改源程序并得到正确的结果。

解:

在终端输入vim greet.c,输入以上示例为:

输入gcc -o greet greet.c进行编译结果如下:

   

回到源码greet.c,我们根据报错信息分段分析。

第一段:

greet.c:4:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
    4 | main()
      | ^~~~

这里错误提示为main()函数无类型,故在main()前加上int。

第二段:

greet.c: In function ‘main’:
greet.c:6:17: error: stray ‘\342’ in program
    6 | char string[] = ���Welcome to Linux!”;
      |                 ^
greet.c:6:18: error: stray ‘\200’ in program
    6 | char string[] = ���Welcome to Linux!”;
      |                  ^
greet.c:6:19: error: stray ‘\234’ in program
    6 | char string[] = ��Welcome to Linux!”;
      |                   ^
greet.c:6:20: error: ‘Welcome’ undeclared (first use in this function)
    6 | char string[] = “Welcome to Linux!”;
      |                    ^~~~~~~
greet.c:6:20: note: each undeclared identifier is reported only once for each function it appears in
greet.c:6:28: error: expected ‘,’ or ‘;’ before ‘to’
    6 | char string[] = “Welcome to Linux!”;
      |                            ^~
greet.c:6:37: error: stray ‘\342’ in program
    6 | char string[] = “Welcome to Linux!���;
      |                                     ^
greet.c:6:38: error: stray ‘\200’ in program
    6 | char string[] = “Welcome to Linux!���;
      |                                      ^
greet.c:6:39: error: stray ‘\235’ in program
    6 | char string[] = “Welcome to Linux!��;
      |

这里错误提示为main()函数内的引号输入为中文模式下输入,需更改为英文状态。根据源码可以很容易发现其他的引号也均需要修改。

第三段:

greet.c: In function ‘display2’:
greet.c:20:8: warning: implicit declaration of function ‘strlen’ [-Wimplicit-function-declaration]
   20 | size = strlen(string1);
      |        ^~~~~~
greet.c:20:8: warning: incompatible implicit declaration of built-in function ‘strlen’
greet.c:2:1: note: include ‘<string.h>’ or provide a declaration of ‘strlen’
    1 | #include <stdio.h>
  +++ |+#include <string.h>
    2 | int display1(char *string);
greet.c:21:19: warning: implicit declaration of function ‘malloc’ [-Wimplicit-function-declaration]
   21 | string2 = (char *)malloc(size + 1);
      |                   ^~~~~~
greet.c:21:19: warning: incompatible implicit declaration of built-in function ‘malloc’
greet.c:2:1: note: include ‘<stdlib.h>’ or provide a declaration of ‘malloc’
    1 | #include <stdio.h>
  +++ |+#include <stdlib.h>
    2 | int display1(char *string);
greet.c:26:17: error: empty character constant
   26 | string2[size+1]='';

这个错误提示包含了三个问题:

  1. 隐式声明函数strlen/malloc的警告:可以通过在代码中添加#include <string.h>#include <stdlib.h>解决。
  2. 不兼容的隐式声明函数警告:这个问题是因为编译器默认隐式声明了strlen和malloc函数,但是实际上这些函数需要在头文件中声明。通过添加上述的头文件可以解决这个警告。
  3. 空字符常量错误:这个问题是因为在代码中有一个空的字符常量'',这是无效的。如果想要将一个字符数组的最后一个元素设为空字符,应该使用单引号括起来的空格字符,即' '。可以将代码中的空字符常量替换为' '来解决这个问题。

修改源码如下:

输入gcc -g test.c -o test进行编译结果如下:

输入./ greet

在23行(for循环处)设置断点:b 24;在29行(printf函数处)设置断点:b 29。此时输入info b查看断点设置情况。

   

输入r运行代码,也可输入n单步运行代码,继续单步运行代码数次,并使用命令查看,发现string2[size-1]的值正确。

继续程序的运行:c

在程序中,第24行代码为:string2[size-i] = string1[i];,这个语句是将字符串string1中的每个字符倒序复制到另一个字符串string2中。但是,在循环中,i的取值范围是从0到size-1,因此在第一次循环中,string2[size-i]实际上是string2[size-0],即string2的最后一个字符,而不是第一个字符。这会导致第一个字符无法被正确赋值。 为了解决这个问题,可以将循环的范围修改为从0到size。这样,在第一次循环中,string2[size-i]就会被正确地赋值为string1中的第一个字符,而不是最后一个字符。修改后的代码如下所示

重新进行编译,结果显示通过。

 


🌍4. 实验心得

  1. 编码注意事项: 在实验中,我学到了在编写代码时需要格外注意当前输入模式,避免在中文输入模式下输入英文符号。这是因为中文输入模式会导致符号被输入法转换,不直接对应ASCII码表中的字符。这种小细节的注意可以避免在后续编译和调试过程中因为字符转换引起的问题,确保代码的准确性和可靠性。
  2. 编译器选项的灵活运用: 通过使用gcc编译器,我掌握了如何通过命令行参数指定编译选项。具体而言,我了解到-Wall选项可开启所有警告信息,有助于发现潜在的错误和问题。同时,使用-g选项能够在编译时生成调试信息,提供更全面的调试支持。这种对编译选项的灵活运用不仅有助于提前发现潜在问题,也为后续的调试工作提供了更充分的信息支持。
  3. 高效调试技巧的应用: 通过实验,我学会了在Linux环境下使用GDB调试器进行代码调试的基本技巧。这包括使用break设置断点、run运行程序以及print打印变量值等命令。这些简洁而强大的调试命令使得在代码调试过程中能够更高效地定位和修复问题,提高了开发效率。通过掌握这些调试技巧,我能够更自信地处理代码中的错误和异常,确保程序的稳定性和可靠性。

📝总结

Linux操作系统的领域就像一片未被勘探的信息大海,引领你勇敢踏入开源系统的神秘领域。这是一场独特的学习冒险,从基本概念到系统架构,逐步揭示更深层次的操作系统原理、命令行工具和高级系统管理的奥秘。


相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
目录
相关文章
|
6天前
|
安全 Linux 数据安全/隐私保护
Vanilla OS:下一代安全 Linux 发行版
【10月更文挑战第30天】
20 0
Vanilla OS:下一代安全 Linux 发行版
|
3天前
|
缓存 网络协议 Linux
Linux操作系统内核
Linux操作系统内核 1、进程管理: 进程调度 进程创建与销毁 进程间通信 2、内存管理: 内存分配与回收 虚拟内存管理 缓存管理 3、驱动管理: 设备驱动程序接口 硬件抽象层 中断处理 4、文件和网络管理: 文件系统管理 网络协议栈 网络安全及防火墙管理
20 4
|
2天前
|
安全 网络协议 Linux
Linux操作系统的内核升级与优化策略####
【10月更文挑战第29天】 本文深入探讨了Linux操作系统内核升级的重要性,并详细阐述了一系列优化策略,旨在帮助系统管理员和高级用户提升系统的稳定性、安全性和性能。通过实际案例分析,我们展示了如何安全有效地进行内核升级,以及如何利用调优技术充分发挥Linux系统的潜力。 ####
15 1
|
5天前
|
物联网 Linux 云计算
Linux操作系统的演变与未来趋势####
【10月更文挑战第29天】 本文深入探讨了Linux操作系统从诞生至今的发展历程,分析了其在服务器、桌面及嵌入式系统领域的应用现状,并展望了云计算、物联网时代下Linux的未来趋势。通过回顾历史、剖析现状、预测未来,本文旨在为读者提供一个全面而深入的视角,以理解Linux在当今技术生态中的重要地位及其发展潜力。 ####
|
7天前
|
Linux 开发者 iOS开发
Python系统调用实战:如何在不同操作系统间游刃有余🐟
本文介绍了 Python 在跨平台开发中的强大能力,通过实际例子展示了如何使用 `os` 和 `pathlib` 模块处理文件系统操作,`subprocess` 模块执行外部命令,以及 `tkinter` 创建跨平台的图形用户界面。这些工具和模块帮助开发者轻松应对不同操作系统间的差异,专注于业务逻辑。
21 2
|
10天前
|
边缘计算 人工智能 运维
Linux操作系统:开源力量的崛起与影响###
一场技术革命的回顾 回溯至1991年,当Linus Torvalds宣布Linux操作系统的诞生时,世界或许并未意识到这一举措将如何深刻地改变技术领域的面貌。本文旨在探讨Linux操作系统的发展历程、核心特性、以及它如何引领了一场开源运动,重塑了软件行业的生态。从最初的个人爱好项目成长为全球最广泛采用的服务器操作系统之一,Linux的故事是技术创新与社区精神共同推动下的辉煌篇章。 ###
|
9天前
|
人工智能 安全 Linux
|
11天前
|
物联网 Linux 5G
Linux操作系统的演变与未来趋势####
本文深入探讨了Linux操作系统的发展历程,从最初的一个学生项目到如今全球最流行的开源操作系统之一。文章将分析Linux的核心优势、关键特性以及它在云计算、物联网和嵌入式系统中的应用前景。通过具体案例展示Linux如何推动技术创新,并预测其在未来技术生态中的角色。本文旨在为读者提供一个全面而深入的理解,帮助他们认识到Linux在现代计算环境中的重要性及其未来的潜力。 ####
|
11天前
|
人工智能 安全 物联网
Linux操作系统的演变与未来:从开源精神到万物互联的基石###
本文是关于Linux操作系统的演变、现状与未来的深度探索。Linux,这一基于Unix的开源操作系统,自1991年由林纳斯·托瓦兹(Linus Torvalds)学生时代创造以来,已经彻底改变了我们的数字世界。文章首先追溯了Linux的起源,解析其作为开源项目的独特之处;随后,详细阐述了Linux如何从一个小众项目成长为全球最广泛采用的操作系统之一,特别是在服务器、云计算及嵌入式系统领域的主导地位。此外,文章还探讨了Linux在推动技术创新、促进协作开发模式以及保障信息安全方面的作用,最后展望了Linux在未来技术趋势中的角色,包括物联网、人工智能和量子计算等前沿领域的潜在影响。 ###
|
15天前
|
运维 物联网 Linux
Linux操作系统的演变与未来趋势####
本文通过探讨Linux操作系统的历史沿革、当前主流版本的特点,以及其在服务器、云计算和物联网等新兴领域的应用,旨在揭示Linux在现代计算环境中的重要性。此外,文章还将分析Linux面临的挑战与机遇,预测其未来的发展趋势。希望通过这篇文章,读者能够更好地理解Linux的价值,并对其未来充满期待。 ####
下一篇
无影云桌面