【正点原子Linux连载】第一章 应用编程概念-摘自【正点原子】I.MX6U嵌入式Linux C应用编程指南V1.1_i.mx6u嵌入式linux c应用编程指南v1.1下载-程序员宅基地

技术标签: linux  嵌入式  

1)实验平台:正点原子阿尔法Linux开发板
2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434
2)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-300792-1-1.html
3)对正点原子Linux感兴趣的同学可以加群讨论:935446741
4)关注正点原子公众号,获取最新资料更新
————————————————

第一章 应用编程概念

对于大多数首次接触Linux应用编程的读者来说,可能对应用编程(也可称为系统编程)这个概念并不太了解,所以在正式学习Linux应用编程之前,笔者有必要向大家介绍这些简单基本的概念,从整体上认识到应用编程为何物?与驱动编程、裸机编程有何不同?
了解本章所介绍的内容是掌握应用编程的先决条件,所以本章主要内容便是对Linux应用编程进行一个简单地介绍,让读者对此有一个基本的认识。

本章将会讨论如下主题内容。
何为系统调用;
何为库函数;
应用程序的main()函数;
应用程序开发环境的介绍。

1.1系统调用
系统调用(system call)其实是Linux内核提供给应用层的应用编程接口(API),是Linux应用层进入内核的入口。不止Linux系统,所有的操作系统都会向应用层提供系统调用,应用程序通过系统调用来使用操作系统提供的各种服务。
通过系统调用,Linux应用程序可以请求内核以自己的名义执行某些事情,譬如打开磁盘中的文件、读写文件、关闭文件以及控制其它硬件外设。
通过系统调用API,应用层可以实现与内核的交互,其关系可通过下图简单描述:
在这里插入图片描述

图 1.1.1 内核、系统调用与应用程序
内核提供了一系列的服务、资源、支持一系列功能,应用程序通过调用系统调用API函数来使用内核提供的服务、资源以及各种各样的功能,如果大家接触过其它操作系统编程,想必对此并不陌生,譬如Windows应用编程,操作系统内核一般都会向应用程序提供应用编程接口API,否则我们将我无法使用操作系统。
应用编程与裸机编程、驱动编程有什么区别?
在学习应用编程之前,相信大家都有过软件开发经验,譬如51、STM32等单片机软件开发、以及嵌入式Linux硬件平台下的驱动开发等,51、STM32这类单片机的软件开发通常是裸机程序开发,并不会涉及到操作系统的概念,那应用编程与裸机编程以及驱动开发有什么区别呢?
就拿嵌入式Linux硬件平台下的软件开发来说,我们大可将编程分为三种,分别为裸机编程、Linux驱动编程以及Linux应用编程。首先对于裸机编程这个概念来说很好理解,一般把没有操作系统支持的编程环境称为裸机编程环境,譬如单片机上的编程开发,编写直接在硬件上运行的程序,没有操作系统支持;狭义上Linux驱动编程指的是基于内核驱动框架开发驱动程序,驱动开发工程师通过调用Linux内核提供的接口完成设备驱动的注册,驱动程序负责底层硬件操作相关逻辑,如果学习过Linux驱动开发的读者,想必对此并不陌生;而Linux应用编程(系统编程)则指的是基于Linux操作系统的应用编程,在应用程序中通过调用系统调用API完成应用程序的功能和逻辑,应用程序运行于操作系统之上。通常在操作系统下有两种不同的状态:内核态和用户态,应用程序运行在用户态、而内核则运行在内核态。
关于应用编程这个概念,以上给大家解释得很清楚了,笔者以实现点亮一个LED功能为例,给大家简单地说明三者之间的区别,LED裸机程序如下所示:
示例代码 1.1.1 LED裸机程序

static void led_on(void)
{
    
    /* 点亮LED硬件操作代码 */
}

static void led_off(void)
{
    
    /* 熄灭LED硬件操作代码 */
}

int main(void)
{
    
    /* 用户逻辑 */
    for ( ; ; ) {
    

        led_on();       //点亮LED
        delay();        //延时
        led_off();      //熄灭LED
        delay();        //延时
    }
}

可以看到在裸机程序当中,LED硬件操作代码与用户逻辑代码全部都是在同一个源文件(同一个工程)中实现的,硬件操作代码与用户逻辑代码没有隔离,没有操作系统支持,代码编译之后直接在硬件平台运行,俗称“裸跑”。我们再来看一个Linux系统下的LED驱动程序示例代码,如下所示:
示例代码 1.1.2 Linux下LED驱动程序

#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/delay.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>

static void led_on(void)
{
    
    /* 点亮LED硬件操作代码 */
}

static void led_off(void)
{
    
    /* 熄灭LED硬件操作代码 */
}

static int led_open(struct inode *inode, struct file *filp)
{
    
    /* 打开设备时需要做的事情 */
}

static ssize_t led_write(struct file *filp, const char __user *buf,
            size_t size, loff_t *offt)
{
    
    int flag;
/* 获取应用层write的数据,存放在flag变量 */
 if (copy_from_user(&flag, buf, size))
        return -EFAULT;

    /* 判断用户写入的数据,如果是0则熄灭LED,如果是非0则点亮LED */
    if (flag)
        led_on();
    else
        led_off();

    return 0;
}

static int led_release(struct inode *inode, struct file *filp)
{
    
    /* 关闭设备时需要做的事情 */
}

static struct file_operations led_fops = {
    
    .owner 	= THIS_MODULE,
    .open  	= led_open,
    .write  	= led_write,
    .release	= led_release,
};

static int led_probe(struct platform_device *pdev)
{
    
    /* 驱动加载时需要做的事情 */
}

static int led_remove(struct platform_device *pdev)
{
    
    /* 驱动卸载时需要做的事情 */
}

static const struct of_device_id led_of_match[] = {
    
    {
     .compatible = "alientek,led", },
    {
     /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, led_of_match);

static struct platform_driver led_driver = {
    
    .driver = {
    
        .owner        	= THIS_MODULE,
        .name        	= "led",
        .of_match_table	= led_of_match,
    },
    .probe  = led_probe,
    .remove = led_remove,
};
module_platform_driver(led_driver);

MODULE_DESCRIPTION("LED Driver");
MODULE_LICENSE("GPL");

以上并不是一个完整的LED驱动代码,如果没有接触过Linux驱动开发的读者,看不懂也没有关系,并无大碍,此驱动程序使用了最基本的字符设备驱动框架编写而成,非常简单;led_fops对象中提供了open、write、release方法,当应用程序调用open系统调用打开此LED设备时会执行到led_open函数,当调用close系统调用关闭LED设备时会执行到led_release函数,而调用write系统调用时会执行到led_write函数,此驱动程序的设定是当应用层调用write写入0时熄灭LED,write写入非0时点亮LED。
驱动程序属于内核的一部分,当操作系统启动的时候会加载驱动程序,可以看到LED驱动程序中仅仅实现了点亮/熄灭LED硬件操作相关逻辑代码,应用程序可通过write这个系统调用API函数控制LED亮灭;接下来我们看看Linux系统下的LED应用程序示例代码,如下所示:
示例代码 1.1.3 Linux下LED应用程序

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

int main(int argc, char **argv)
{
    
    int fd;
    int data;

    fd = open("/dev/led", O_WRONLY);//打开LED设备(假定LED的设备文件为/dev/led)
    if (0 > fd)
        return -1;

    for ( ; ; ) {
    

        data = 1;
        write(fd, &data, sizeof(data)); //写1点亮LED
        sleep(1);       //延时1秒

        data = 0;
        write(fd, &data, sizeof(data)); //写0熄灭LED
        sleep(1);       //延时1秒
    }

    close(fd);
    return 0;
}

此应用程序也非常简单,仅只需实现用户逻辑代码即可,循环点亮、熄灭LED,并不需要实现硬件操作相关,示例代码中调用了open、write、close这三个系统调用API接口,open和close分别用于打开/关闭LED设备,write写入数据传给LED驱动,传入0熄灭LED,传入非0点亮LED。
LED应用程序与LED驱动程序是分隔、分离的,它们单独编译,它们并不是整合在一起的,应用程序运行在操作系统之上,有操作系统支持,应用程序处于用户态,而驱动程序处于内核态,与纯粹的裸机程序存在着质的区别。Linux应用开发与驱动开发是两个不同的方向,将来在工作当中也会负责不同的任务、解决不同的问题。
关于本小节系统调用概念相关的内容就介绍到这里了,接下来向大家介绍库函数。
1.2库函数
前面给大家介绍了系统调用,系统调用是内核直接向应用层提供的应用编程接口,譬如open、write、read、close等,关于这些系统调用后面会给大家进行详细介绍。编写应用程序除了使用系统调用之外,我们还可以使用库函数,本小节来聊一聊库函数。
库函数也就是C语言库函数,C语言库是应用层使用的一套函数库,在Linux下,通常以动态(.so)库文件的形式提供,存放在根文件系统/lib目录下,C语言库函数构建于系统调用之上,也就是说库函数其实是由系统调用封装而来的,当然也不能完全这么说,原因在于有些库函数并不调用任何系统调用,譬如一些字符串处理函数strlen()、strcat()、memcpy()、memset()、strchr()等等;而有些库函数则会使用系统调用来帮它完成实际的操作,譬如库函数fopen内部调用了系统调用open()来帮它打开文件、库函数fread()就利用了系统调用read()来完成读文件操作、fwrite()就利用了系统调用write()来完成写文件操作。
Linux系统内核提供了一系列的系统调用供应用层使用,我们直接使用系统调用就可以了呀,那为何还要设计出库函数呢?事实上,有些系统调用使用起来并不是很方便,于是就出现了C语言库,这些C语言库函数的设计是为了提供比底层系统调用更为方便、更为好用、且更具有可移植性的调用接口。
来看一看它们之间的区别:
库函数是属于应用层,而系统调用是内核提供给应用层的编程接口,属于系统内核的一部分;
库函数运行在用户空间,调用系统调用会由用户空间(用户态)陷入到内核空间(内核态);
库函数通常是有缓存的,而系统调用是无缓存的,所以在性能、效率上,库函数通常要优于系统调用;
可移植性:库函数相比于系统调用具有更好的可移植性,通常对于不同的操作系统,其内核向应用层提供的系统调用往往都是不同,譬如系统调用的定义、功能、参数列表、返回值等往往都是不一样的;而对于C语言库函数来说,由于很多操作系统都实现了C语言库,C语言库在不同的操作系统之间其接口定义几乎是一样的,所以库函数在不同操作系统之间相比于系统调用具有更好的可移植性。
以上便上它们之间一个大致的区别,从实现者的角度来看,系统调用与库函数之间有根本的区别,但从用户使用角度来看,其区别并不重要,它们都是C语言函数。在实际应用编程中,库函数和系统调用都会使用到,所以对于我们来说,直接把它们当做是C函数即可,知道你自己调用的函数是系统调用还是库函数即可,不用太过于区分它们之间的差别。
所以应用编程简单点来说就是:开发Linux应用程序,通过调用内核提供的系统调用或使用C库函数来开发具有相应功能的应用程序。
1.3标准C语言函数库
在Linux系统下,使用的C语言库为GNU C语言函数库(也叫作glibc,其网址为http://www.gnu.org/software/libc/),作为Linux下的标准C语言函数库。
进入到http://www.gnu.org/software/libc/网址,如下所示:
在这里插入图片描述

图 1.3.1 glibc官网
点击上面的Sources选项可以查看它的源码实现:
在这里插入图片描述

图 1.3.2 获取源码的方式
glibc源码的获取方式很简单,直接直接从git仓库下载,也可以通过ftp下载,如果大家有兴趣、或者想要了解某一个库函数它的具体实现,那么就可以获取到它源码来进行分析,好了,这里就不再多说了!
确定Linux系统的glibc版本
前面提到过了,C语言库是以动态库文件的形式提供的,通常存放在/lib目录,它的命名方式通常是libc.so.6,不过这个是一个软链接文件,它会链接到真正的库文件。
进入到Ubuntu系统的/lib目录下,笔者使用的Ubuntu版本为16.04,在我的/lib目录下并没有发现libc.so.6这个文件,其实是在/lib/x86_64-linux-gnu目录下,进入到该目录:
在这里插入图片描述

图 1.3.3 libc.so.6文件
可以看到libc.so.6链接到了libc-2.23.so库文件,2.23表示的就是这个glibc库的版本号为2.23。除此之外,我们还可以直接运行该共享库来获取到它的信息,如下所示:

图 1.3.4 确定glibc版本号
从打印信息可以看到,笔者所使用的Ubuntu系统对应的glibc版本号为2.23。
1.4main函数
对学习过C语言编程的读者来说,譬如单片机编程、Windows应用编程等,main函数想必大家再熟悉不过了,很多编程开发都是以main函数作为程序的入口函数,同样在Linux应用程序中,main函数也是作为应用程序的入口函数存在,main函数的形参一般会有两种写法,如果执行应用程序无需传参,则可以写成如下形式:
示例代码 1.4.1 main函数写法之无传参

int main(void)
{
    
    /* 代码 */
}

如果在执行应用程序的时候需要向应用程序传递参数,则写法如下:
示例代码 1.4.2 main函数写法之有传参
int main(int argc, char **argv)

{
    
    /* 代码 */
}

argc形参表示传入参数的个数,包括应用程序自身路径和程序名,譬如运行当前目录下的hello可执行文件,并且传入参数,如下所示:
./hello 112233
那么此时参数个数为2,并且这些参数都是作为字符串的形式传递给main函数:
argv[0]等于"./hello"
argv[1]等于"112233"
有传参时main函数的写法并不只有这一种,只是这种写法最常用,对于其它的写法,后面学习过程中如果遇到了再给大家进行讲解,这里暂时先不去管。
1.5本书使用的开发环境
对于编程开发,大家可能都比较关心开发环境的问题,譬如本书将使用什么IDE编写应用程序之类的问题,本小节将对开发环境的问题进行一个简单介绍。
首先,本书分为三篇内容,在前言部分已经向各位读者介绍了本书的内容规划,分为入门篇、提高篇以及进阶篇。因为是Linux应用编程,所以本书将会在Linux操作系统环境下编写示例代码,为了同正点原子的其它开发文档保持一致,选择Ubuntu操作系统,推荐大家使用16.04或14.04版本的Ubuntu系统,个人觉得这两个版本比较稳定;除了使用Ubuntu系统外,大家还可以选择其它Linux发行版,譬如CentOS、Redhat(红帽)等。
在Linux操作系统下,也有很多比较好用的IDE软件,可以帮助我们更为轻松的进行软件开发,譬如Eclipse、vscode等,如果你会使用Eclipse,可以在Ubuntu系统下安装Eclipse进行Linux应用开发,1.5.1小节介绍了如何在Ubuntu系统下安装Eclipse;如果你不会使用Eclipse,那就建议你使用vscode,同样本书也是使用vscode,与正点原子的驱动开发文档保持一致;vscode的安装方法和使用方法本书不再介绍,相信大家在自己的Ubuntu系统下已经安装好了,如果没有安装的,直接参考“开发板光盘资料A-基础资料/【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5.pdf”文档第四章的4.5小节内容进行安装即可!
Tips:注意,本文档并不介绍Eclipse IDE的使用方法,笔者也用的不多,只是告诉大家可以在Ubuntu使用这个IDE,并且后面给出了安装方法,如果你以前经常使用它开发软件,你可以尝试使用它在Ubuntu下开发Linux应用程序,如果你没用过就不要去碰了。用什么IDE都不重要,哪怕你直接使用vi编写程序都可以,我们的重点是学习应用编程!而不是学习IDE怎么用。
vscode是一个代码编辑器,提供了很多好用的插件,譬如语法检测、高亮显示、智能补全等,大家可以根据自己的选择安装插件,在驱动开发指南文档中也都有介绍。
入门篇章节内容中,主要向大家介绍了Linux应用编程所涉及到的各个知识点以及各种系统调用和库函数,本部分内容所编写的示例代码,均是在Ubuntu系统下进行测试、验证,也就是在Ubuntu系统下执行测试程序以验证所学知识内容。所以在该部分内容中,本书使用vscode+gcc的方式开发应用程序,vscode作为代码编辑器、gcc作为编译器,使用vscode编写完代码之后再用gcc编译源码,得到可在PC端Ubuntu系统下运行的可执行文件。gcc的使用方法在驱动开发指南中有介绍,参考“开发板光盘资料A-基础资料/【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5.pdf”文档第三章的内容。
提高篇章节内容中,将会以正点原子阿尔法I.MX6U Linux开发板为例,向大家介绍如何编写应用程序控制开发板上的各种硬件外设,所以编写的应用程序是需要在开发板上运行的,阿尔法I.MX6U开发板是ARM架构硬件平台,所以源码需要使用交叉编译工具(ARM架构下的gcc编译器)进行编译,得到可在开发板上运行的可执行文件。所以在第二篇章节内容中,本书使用vscode+ARM gcc(交叉编译工具)的方式开发应用程序。
入门篇和提高篇章节内容中所编写的示例代码只有单个.c源文件,但是对于一个真正的Linux应用程序项目来说,其原文件的个数肯定不止一个,可能有几十上百个,这个时候可能就需要用到Makefile来组织工程源文件。直接通过Makefile来组织工程,对于一个大型软件工程来说通常是比较困难的,需要程序员对Makefile能够熟练使用,譬如Linux内核源码、U-Boot源码等都是直接使用Makefile进行管理。对于一般程序员来说,很难做到熟练使用Makefile。在第三篇(进阶篇)章节内容中,会向大家介绍cmake工具,使用cmake来管理我们的源码工程,相比于直接使用Makefile,使用cmake会打打降低难度,提高我们的开发效率!
进阶篇章节内容中,会给大家介绍一些Linux实战小项目,通过学习进一步提升Linux应用编程能力,本部内容将会使用cmake+vscode进行开发,其实cmake在实际的项目当中用的还是比较多的,譬如很多的开源软件都会选择使用cmake来构建、配置工程源码,学习了之后,相信大家在今后的工作当中也会用到。
关于本小节的内容到这里就结束了,下一章开始将正式进入到应用编程学习之路,大家加油!
1.5.1Ubuntu系统下安装Eclipse
本小节介绍如何在Ubuntu系统下安装Eclipse,笔者使用的Ubuntu系统版本号为16.04.5,其它版本笔者未进行验证,不过大家试一试,如果出现了问题,再根据提示找到相应的解决办法!
Eclipse是一个开源的IDE,基于java语言开发的可扩展开发平台,支持很多插件,可用于诸如java、C/C++、PHP、Android等编程语言的软件开发,关于更加详细的介绍大家自己去了解,本书不再介绍!
㈠下载Eclipse
开发板资料包中提供了Eclipse安装包,路径为:开发板光盘->3、软件->eclipse-cpp-2020-12-R-linux-gtk-x86_64.tar.gz。
首先我们要下载Eclipse安装包,进入到Eclipse官网:https://www.eclipse.org/,如下所示:
在这里插入图片描述

图 1.5.1 Eclipse官网
点击右上角“Download”按钮进入到下载页面:
在这里插入图片描述

图 1.5.2 Download页面
点击下边的“Download Package”选项:
在这里插入图片描述

图 1.5.3 package列表
当前页面显示的是最新版本的软件包,可以看到Eclipse的最新版本是2021-03,上图右下角列出了其它的版本软件包的链接地址,这里笔者选择2020-12,也就是4.18版本作为演示,其它版本笔者没测试过,理论上都是可以的。
点击4.18版本链接地址,页面跟上图一样,因为是使用Eclipse进行C语言应用程序开发,所以选择“Eclipse IDE for C/C++ Developers”软件包,选择Linux系统的安装包,点击下图红框中的x86_64链接:
在这里插入图片描述

图 1.5.4 C/C++ IDE
点击之后会进入到下载界面,点击下图中的“Download”即可下载:
![(https://img-blog.csdnimg.cn/54c6c37654bc4059ace99903831ac0cf.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl81NTc5NjU2NA==,size_16,color_FFFFFF,t_70)
在这里插入图片描述

图 1.5.5 下载
下载完之后会得到压缩包文件“eclipse-cpp-2020-12-R-linux-gtk-x86_64.tar,gz”:
在这里插入图片描述

图 1.5.6 Eclipse压缩包文件
㈡、下载jdk
开发板资料包中提供了jdk,路径为:开发板光盘->3、软件->jdk-8u291-linux-x64.tar.gz。
因为Eclipse是基于java语言开发的,所以它依赖于java jdk,所以我们要下载,进入到https://www.oracle.com/cn/java/technologies/javase-downloads.html网页,如下所示:
在这里插入图片描述

图 1.5.7 jdk下载主页
我们往下翻找到Java SE8,如下所示:
在这里插入图片描述

图 1.5.8 Java SE8
点击JDK Download进入到jdk8下载页面,往下翻找到软件包下载列表:
在这里插入图片描述

图 1.5.9 jdk8下载页面
可以看到上图列举出了很多不同操作系统以及硬件平台的jdk包,操作系统包括Linux、macOS以及Windows等,还有不同的硬件平台,笔者用的是64位的Ubuntu系统,所以选择“Linux x64 Compressed Archive”,点击后边“jdk-8u291-linux-x64.tar.gz”下载。之后会弹出如下界面:
在这里插入图片描述

图 1.5.10 下载
勾选图中所示的选项,之后点击进行下载。下载需要登录Oracle账户,譬如下图所示,填写用户名、密码点击登录之后才能下载;没有账户的读者需要点击下面的“创景账户”进行创建。
在这里插入图片描述

图 1.5.11 登录Oracle账户
下载完之后得到一个压缩包文件:
在这里插入图片描述

图 1.5.12 jdk压缩包文件
㈢、安装Eclipse
首先把前面下载好的两个压缩包文件拷贝到Ubuntu系统用户家目录下,如下所示:
在这里插入图片描述

图 1.5.13 将压缩包文件拷贝到Ubuntu系统
接着将eclipse-cpp-2020-12-R-linux-gtk-x86_64.tar.gz压缩包文件解压到/opt目录下,如下所示:
sudo tar -xzf eclipse-cpp-2020-12-R-linux-gtk-x86_64.tar.gz -C /opt/
在这里插入图片描述

图 1.5.14 解压eclipse-cpp-2020-12-R-linux-gtk-x86_64.tar.gz文件
执行解压命令的时候,需要加上sudo,这样才能有权限将压缩文件解压到/opt目录下,解压之后会在/opt目录下生成eclipse文件夹,如下所示:
在这里插入图片描述

图 1.5.15 eclipse文件夹
这样Eclipse就安装完成了,我们下载的这个压缩包是一个免安装的,直接解压就可以了,eclipse目录就是软件的安装目录了,如下所示:
在这里插入图片描述

图 1.5.16 Eclipse安装目录
接下来创建一个桌面快捷方式,可以通过双击桌面图标来打开Eclipse软件。首先进入到桌面目录下,如下所示:
在这里插入图片描述

图 1.5.17 进入桌面目录
笔者的Ubuntu系统配置的是中文语言环境,如果你的是英文环境,那么对应的应该是Desktop目录。在该目录下创建一个名为eclipse.desktop的文件,将以下内容写入到该文件中:
[Desktop Entry]
Encoding=UTF-8
Name=Eclipse
Comment=Eclipse
Exec=/opt/eclipse/eclipse
Icon=/opt/eclipse/icon.xpm
Terminal=false
StartupNotify=true
Type=Application
Categories=Application;Development;
在这里插入图片描述

图 1.5.18 eclipse.desktop文件中的内容
其中“Exec=”后面为eclipse安装目录下的eclipse可执行文件的路径,“Icon=”后面为eclipse安装目录下的图标图片的路径,编辑完成之后保存退出。最后为eclipse.desktop文件添加上可执行权限:
chmod u+x eclipse.desktop
完成之后,Ubuntu系统桌面上会出现Eclipse软件图标快捷方式:
在这里插入图片描述

图 1.5.19 桌面图标
㈣、安装jdk
将jdk压缩包jdk-8u291-linux-x64.tar.gz解压到/opt目录下:
sudo tar -xzf jdk-8u291-linux-x64.tar.gz -C /opt/
在这里插入图片描述

图 1.5.20 解压jdk-8u291-linux-x64.tar.gz文件
解压完成之后会在/opt目录下生成jdk1.8.0_291文件夹,如下所示:
在这里插入图片描述

图 1.5.21 jdk1.8.0_291文件夹
接下来需要配置环境变量,打开用户家目录下的.bashrc(vi ~/.bashrc)文件,在该文件末尾添加如下内容:

jdk环境配置

export JDK_HOME=/opt/jdk1.8.0_291
export JRE_HOME=${
    JDK_HOME}/jre
export CLASSPATH=.:${
    JDK_HOME}/lib:${
    JRE_HOME}/lib:$CLASSPATH
export PATH=${
    JDK_HOME}/bin:$PATH

在这里插入图片描述

图 1.5.22 配置.bashrc文件
环境变量JDK_HOME指定了jdk的路径。文件内容编辑完成之后保存退出,接着使用source命令运行.bashrc脚本使我们的配置生效:
source ~/.bashrc
jdk到这里就安装完成了,可以检查看看jdk有没有安装成功,在终端下执行java -version命令:
在这里插入图片描述

图 1.5.23 验证jdk安装是否成功
还有最好一个步骤需要完成,将eclipse与jdk联系起来,进入到Eclipse安装目录下,在该目录下创建一个名为jre的文件夹:
在这里插入图片描述

图 1.5.24 创建jre目录
进入到jre目录下,创建一个软链接文件指向jdk目录下的bin目录,如下所示:
在这里插入图片描述

图 1.5.25 创建软链接文件
㈤、测试
接下来打开Eclipse软件,创建一个简单的C语言工程进行测试,在Ubuntu系统桌面上双击Eclipse图标打开Eclipse:
在这里插入图片描述

图 1.5.26 启动界面
Eclipse启动之后会首先让用户设置一个工作目录,如下所示:
在这里插入图片描述

图 1.5.27 设置工作目录
直接使用默认的路径即可,点击Launch。
在这里插入图片描述

图 1.5.28 软件的欢迎界面
点击“Create a new C/C++ project”可以创建一个C语言应用工程,具体的步骤的就不再演示了。
本小节内容到此结束。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_55796564/article/details/119602302

智能推荐

在compute node上安装neutron时,出错neutron ValueError: :5672_在执行脚本进行neutron网络服务安装时报错是什么原因?-程序员宅基地

文章浏览阅读1.1k次。这个是由于没有按住奥_在执行脚本进行neutron网络服务安装时报错是什么原因?

SSM整合_<!--过滤静态资源--> <mvc:resources location="/css/" -程序员宅基地

文章浏览阅读93次。springmvc(view 视图层) ,spring(service业务层) ,Mybatis (dao持久层)1.spring整合springmvc:springmvc配置文件:<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans..._

"当你有一个目标时,就请朝着它努力,你一定会成功的"--世界杯进球记录第一射手克劳泽...-程序员宅基地

文章浏览阅读212次。德国足球队老将克劳泽,一生四次参加世界杯(2002, 2006, 2010, 2014),总共打入16粒进球,是世界杯进球记录拥有者。他的成功,折射出德国人身上优秀的光芒。●童年克洛泽是在1978年出生在波兰的奥博莱,但那里是波兰最大的德裔民族聚居地。从血统上来讲,克洛泽祖祖辈辈都是日耳曼人,而Klose就是最古老的日耳曼姓氏之一。  造成这一切的都是“历史遗留问题”,奥博莱地区在二..._德国球星克劳泽射门

bootstrap练习题-程序员宅基地

文章浏览阅读1.6k次。什么是BootStrap框架Bootstrap 是一个用于快速开发 Web 应用程序和网站的前端框架。Bootstrap 是基于 HTML、CSS、JAVASCRIPT 的前端框架,之所以它能够帮我们快速构建一个前端应用是因为它实现了很多默认的网页样式效果,我们只需要引用它实现的效果即可获得一个漂亮的网页Html、Css和BootStrap框架的关系是什么1.bootstrap就是实现了很多..._bootstrap练习题

Dword、LPSTR、LPWSTR、LPCSTR、LPCWSTR、LPTSTR、LPCTSTR_pcstr 变量-程序员宅基地

文章浏览阅读529次。L表示long指针,这是为了兼容Windows 3.1等16位操作系统遗留下来的,在win32中以及其他的32为操作系统中, long指针和near指针及far修饰符都是为了兼容的作用,没有实际意义。即win32中,long,near,far指针与普通指针没有区别,LP 与P是等效的。P表示这是一个指针。 T表示_T宏,这个宏用来表示你的字符是否使用UNICODE, 如果你的程序定义了_pcstr 变量

numpy专题:ndarray常用函数及属性_在ndarray中用什么函数创建等比数列-程序员宅基地

文章浏览阅读474次。import numpy as np#创建一位数组arr1 = np.array([1,2,3,4])print(arr1)[1 2 3 4]#创建二维数组(4行3列)arr2 = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])print(arr2)[[ 1 2 3 4] [ 5 6 7 8] [ 9 10 11 12]]#查看数组属性print('_在ndarray中用什么函数创建等比数列

随便推点

生活大爆炸第三季 那些精妙的台词翻译_tushy face-程序员宅基地

文章浏览阅读2k次。第三季的精彩语录值得记录。_tushy face

邮件发送与接收,支持163邮箱、outlook邮箱、exchange邮箱_. 集成&自动化中配置发送邮件节点,发件人邮箱账号支持哪些邮箱类型-程序员宅基地

文章浏览阅读2.4k次。邮件发送与接收,支持163邮箱、outlook邮箱、exchange邮箱依赖的jar包邮件收发公共服务层实现package com.example.demo.service.impl;import com.example.demo.model.EmailMessageBO;import com.example.demo.model.EmailSendBO;import com.example.demo.model.FileBean;import com.example.demo.serv_. 集成&自动化中配置发送邮件节点,发件人邮箱账号支持哪些邮箱类型

android pppd参数介绍,android 3G pppd 调试记录-程序员宅基地

文章浏览阅读675次。android 3G pppd 调试记录。1. JAVA 部分android/development/data/etc/apns-conf_sdk.xml ---> system/etc/apns-conf.xml注意 apns 的版本,apn="3gnet"mcc="460"mnc="01"proxy=""port=""user=""server=""password=""type..._pppd 中拨号mcc和mnc 配置

php okhttp3 上传文件,Android使用OKHttp库实现视频文件的上传到服务器功能-程序员宅基地

文章浏览阅读697次。1 服务器接口简介此处我使用的服务器接口是使用Flask编写,具体实现代码:# -*- coding: utf-8 -*-from flask import Flask, render_template, jsonify, requestimport timeimport osimport base64app = Flask(__name__)UPLOAD_FOLDER = 'E:\myuploa..._okhttp3上传视频

android常用的必备基础知识_android必背知识-程序员宅基地

文章浏览阅读151次。首先从四大组件说起: Activity: 生命周期: activity三种状态:运行(运行在最前端)、停止(不可见,完全被覆盖)、暂停(可见,但前端还有其他activity) 生命周期相关的方法:onCreate-onStart-onResume-onPause-onStop-onDestory-onRestart 切换时如果要保存数据, 可以重写: onSaveInstanceStat..._android必背知识

matplotlib的imshow函数显示灰度图像要设置vmin和vmax2个参数_imshow vmin-程序员宅基地

文章浏览阅读4.1k次,点赞4次,收藏13次。matplotlib的imshow函数在显示灰度图像的时候要设置vmin和vmax2个函数_imshow vmin