首页 > 系统相关 >linux内核-2.Linux 内核makefile编译过程

linux内核-2.Linux 内核makefile编译过程

时间:2024-01-29 17:44:53浏览次数:22  
标签:built Makefile make makefile vmlinux 内核 linux arch arm

1 zImage编译

image
_all 是默认目标,如果使用命令make或者make all编译 Linux 的话此目标就会被匹配。
KBUILD_EXTMOD 为空的,因此194 行的代码成立, 因此_all依赖all。all又依赖vmlinux,开始编译vmlinux。

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_v7_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage -j16

1.1 vmlinux编译

找到vmlinux目标开始分析:
image
目标 vmlinux 依赖 scripts/link-vmlinux.sh $(vmlinux-deps) FORCE。

vmlinux-deps= $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN)

其中:

KBUILD_VMLINUX_INIT= $(head-y) $(init-y)
KBUILD_VMLINUX_MAIN = $(core-y) $(libs-y) $(drivers-y) $(net-y)
KBUILD_LDS= arch/$(SRCARCH)/kernel/vmlinux.lds  //链接脚本

综上所述,vmlinux 的依赖为:

scripts/link-vmlinux.sh
$(head-y) 、$(init-y)、$(core-y) 、
$(libs-y) 、$(drivers-y) 、$(net-y)、arch/arm/kernel/vmlinux.lds 和 FORCE

1.1.1 head-y

head-y 定义在文件 arch/arm/Makefile 中:

135 head-y := arch/arm/kernel/head$(MMUEXT).o

当不使能 MMU 的话 MMUEXT=-nommu,如果使能 MMU 的话为空,因此 head-y为:
head-y = arch/arm/kernel/head.o

1.1.2 init-y/drivers-y和net-y

顶层Makefile内容如下:
image
展开后:

init-y = init/built-in.o
drivers-y = drivers/built-in.o sound/built-in.o firmware/built-in.o
net-y = net/built-in.o

1.1.3 libs-y

顶层Makefile中:

561 libs-y := lib/

在arch/arm/Makefile中,对libs-y又追加了:
libs-y := arch/arm/lib/ $(libs-y)
展开后:
libs-y = arch/arm/lib lib/
回到顶层Makefile:

900 libs-y1 := $(patsubst %/, %/lib.a, $(libs-y))
901 libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y))
902 libs-y := $(libs-y1) $(libs-y2)

展开后:
libs-y = arch/arm/lib/lib.a lib/lib.a arch/arm/lib/built-in.o lib/built-in.o

1.1.4 core-y

顶层Makefile中:

532 core-y := usr/
......
887 core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/

在 arch/arm/Makefile 中会对 core-y 进行追加,代码如下:

269 core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/
270 core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ)
271 core-$(CONFIG_VFP) += arch/arm/vfp/
272 core-$(CONFIG_XEN) += arch/arm/xen/
273 core-$(CONFIG_KVM_ARM_HOST) += arch/arm/kvm/
274 core-$(CONFIG_VDSO) += arch/arm/vdso/
275
276 # If we have a machine-specific directory, then include it in the 
build.
277 core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
278 core-y += arch/arm/probes/
279 core-y += arch/arm/net/
280 core-y += arch/arm/crypto/
281 core-y += arch/arm/firmware/
282 core-y += $(machdirs) $(platdirs)

比如使能 VFP 的话就会在.config中有 CONFIG_VFP=y 这一行,那么 core-y 就会追加“arch/arm/vfp/”。
顶层 Makefile 中还有:

897 core-y := $(patsubst %/, %/built-in.o, $(core-y))

最终 core-y 的值为:

core-y = usr/built-in.o		arch/arm/vfp/built-in.o \
arch/arm/vdso/built-in.o	arch/arm/kernel/built-in.o \
arch/arm/mm/built-in.o 		arch/arm/common/built-in.o \
arch/arm/probes/built-in.o 	arch/arm/net/built-in.o \
arch/arm/crypto/built-in.o 	arch/arm/firmware/built-in.o \
arch/arm/mach-imx/built-in.o 	kernel/built-in.o\
mm/built-in.o 			fs/built-in.o \
ipc/built-in.o 			security/built-in.o \
crypto/built-in.o 		block/built-in.o

可以看到和 uboot 一样这些变量都是一些 built-in.o 或.a 等文件,都是将相应目录中的源码文件进行编译,然后在各自目录下生成 built-in.o 文件,有些生成了.a 库文件。最终将这些 built-in.o 和.a 文件进行链接即可形成 ELF 格式的可执行文件,也就是 vmlinux。但是链接是需要链接脚本的,vmlinux 的依赖 arch/arm/kernel/vmlinux.lds 就是整个 Linux 的链接脚本。

vmlinux的依赖产生完后,调用+$(call if_changed,link-vmlinux)链接生成 vmlinux。
命令“+$(call if_changed,link-vmlinux)”表示将$(call if_changed,link-vmlinux)的结果作为最终生成 vmlinux 的命令,前面的“+”表示该命令结果不可忽略。$(call if_changed,link-vmlinux)是调用函数 if_changed,link-vmlinux 是函数 if_changed 的参数,函数 if_changed 定义在文件 scripts/Kbuild.include 中:
image

uboot顶层makefile-2编译过程有具体分析 if_changed。

总结:当依赖比目标新的时候,或者命令有改变的时候,if_changed 就会执行一些命令
“@set -e”告诉 bash,如果任何语句的执行结果不为 true(也就是执行出错)的话就直接退出。
$(echo-cmd)用于打印命令执行过程,比如在链接 vmlinux 的时候就会输出“LINK vmlinux”。$(cmd_$(1))中的$(1)表示参数,也就是 link-vmlinux,因此$(cmd_$(1))表示执行 cmd_link-vmlinux 的内容。

打开.vmlinux.cmd文件内容如下:
cmd_vmlinux := /bin/bash scripts/link-vmlinux.sh arm-linux-gnueabihf-ld -EL -p --no-undefined -X --pic-veneer --build-id
cmd_link-vmlinux 在顶层 Makefile 中定义如下:

914 # Final link of vmlinux
915 cmd_link-vmlinux = $(CONFIG_SHELL) $< $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux)
916 quiet_cmd_link-vmlinux = LINK $@

第 915 行就是 cmd_link-vmlinux 的值,其中 CONFIG_SHELL=/bin/bash,$<表示目标 vmlinux的第一个依赖文件,也就是 scripts/link-vmlinux.sh。
LD= arm-linux-gnueabihf-ld -EL,LDFLAGS 为空。LDFLAGS_vmlinux 的值由顶层 Makefile 和arch/arm/Makefile 这两个文件共同决定,最终:
LDFLAGS_vmlinux=-p --no-undefined -X --pic-veneer --build-id
因此 cmd_link-vmlinux 最终的值:
cmd_link-vmlinux = /bin/bash scripts/link-vmlinux.sh arm-linux-gnueabihf-ld -EL -p --no-undefined -X --pic-veneer --build-id
cmd_link-vmlinux 会调用 scripts/link-vmlinux.sh 这个脚本来链接出 vmlinux。脚本内容如下:
image
vmliux_link 就是最终链接出 vmlinux 的函数,判断 SRCARCH 是否不等于“um”,因为 SRCARCH=arm,因此条件成立。执行:

${LD} ${LDFLAGS} ${LDFLAGS_vmlinux} -o ${2} \
	-T ${lds} ${KBUILD_VMLINUX_INIT} \
	--start-group ${KBUILD_VMLINUX_MAIN} --end-group ${1}

这三行代码应该很熟悉了! 就是普通的链接操作,连接脚本为lds= ./arch/arm/kernel/vmlinux.lds ,需要链接的文件由变量 KBUILD_VMLINUX_INIT 和KBUILD_VMLINUX_MAIN 来决定,这两个变量在前面讲过了:

KBUILD_VMLINUX_INIT= $(head-y) $(init-y)
KBUILD_VMLINUX_MAIN = $(core-y) $(libs-y) $(drivers-y) $(net-y)
KBUILD_LDS= arch/$(SRCARCH)/kernel/vmlinux.lds  //链接脚本

第 217 行调用 vmlinux_link 函数来链接出 vmlinux。
编译时V=1即可看到详细LD链接过程如下:
image
总结:将各个子目录下的 built-in.o、.a 等文件链接在一起,最终生成 vmlinux 这个 ELF 格式的可执行文件。链接脚本为arch/arm/kernel/vmlinux.lds,链接过程是由shell脚本scripts/link-vmlinux.s来完成的。

1.1.5.1 built-in.o产生过程

vmliux 依赖 vmlinux-deps:
vmlinux-deps= $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN)
这些变量进行展开:

vmlinux-deps = arch/arm/kernel/vmlinux.lds
		arch/arm/kernel/head.o \
		init/built-in.o              usr/built-in.o \
		arch/arm/vfp/built-in.o      arch/arm/vdso/built-in.o \
		arch/arm/kernel/built-in.o   arch/arm/mm/built-in.o \
		arch/arm/common/built-in.o   arch/arm/probes/built-in.o \
		arch/arm/net/built-in.o      arch/arm/crypto/built-in.o \
		arch/arm/firmware/built-in.o arch/arm/mach-imx/built-in.o \
		kernel/built-in.o            mm/built-in.o \
		fs/built-in.o                ipc/built-in.o \
		security/built-in.o          crypto/built-in.o\
		block/built-in.o             arch/arm/lib/lib.a\
		lib/lib.a                    arch/arm/lib/built-in.o\
		lib/built-in.o               drivers/built-in.o \
		sound/built-in.o             firmware/built-in.o \
		net/built-in.o

除了 arch/arm/kernel/vmlinux.lds 以外,其他都是要编译链接生成的。顶层 Makefile 中有如下代码:
937 $(sort $(vmlinux-deps)): $(vmlinux-dirs) ;
sort 是排序函数,用于对 vmlinux-deps 的字符串列表进行排序,并且去掉重复的单词。可以看出 vmlinux-deps 依赖 vmlinux-dirs,vmlinux-dirs 也定义在顶层 Makefile 中,定义如下:

889 vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
890 		$(core-y) $(core-m) $(drivers-y) $(drivers-m) \
891 		$(net-y) $(net-m) $(libs-y) $(libs-m)))

image

因此展开vmlinux-dirs为:

vmlinux-dirs = init        usr             arch/arm/vfp \
		arch/arm/vdso arch/arm/kernel      arch/arm/mm \
		arch/arm/common arch/arm/probes    arch/arm/net \
		arch/arm/crypto arch/arm/firmware  arch/arm/mach-imx\
		kernel                             mm        fs \
		ipc                                security  crypto \
		block                              drivers   sound \
		firmware                           net       arch/arm/lib \
		lib

在顶层 Makefile 中有如下代码:

946 $(vmlinux-dirs): prepare scripts
947 	$(Q)$(MAKE) $(build)=$@

第947行内容进行展开:
@ make -f ./scripts/Makefile.build obj=$@
$@在makefile中表示target,因此就是为vmlinux-dirs 的值,将 vmlinux-dirs 中的这些目录全部带入到命令中:

@ make -f ./scripts/Makefile.build obj=init
@ make -f ./scripts/Makefile.build obj=usr
@ make -f ./scripts/Makefile.build obj=arch/arm/vfp
@ make -f ./scripts/Makefile.build obj=arch/arm/vdso
@ make -f ./scripts/Makefile.build obj=arch/arm/kernel
@ make -f ./scripts/Makefile.build obj=arch/arm/mm
@ make -f ./scripts/Makefile.build obj=arch/arm/common
@ make -f ./scripts/Makefile.build obj=arch/arm/probes
@ make -f ./scripts/Makefile.build obj=arch/arm/net
@ make -f ./scripts/Makefile.build obj=arch/arm/crypto
@ make -f ./scripts/Makefile.build obj=arch/arm/firmware
@ make -f ./scripts/Makefile.build obj=arch/arm/mach-imx
@ make -f ./scripts/Makefile.build obj=kernel
@ make -f ./scripts/Makefile.build obj=mm
@ make -f ./scripts/Makefile.build obj=fs
@ make -f ./scripts/Makefile.build obj=ipc
@ make -f ./scripts/Makefile.build obj=security
@ make -f ./scripts/Makefile.build obj=crypto
@ make -f ./scripts/Makefile.build obj=block
@ make -f ./scripts/Makefile.build obj=drivers
@ make -f ./scripts/Makefile.build obj=sound
@ make -f ./scripts/Makefile.build obj=firmware
@ make -f ./scripts/Makefile.build obj=net
@ make -f ./scripts/Makefile.build obj=arch/arm/lib
@ make -f ./scripts/Makefile.build obj=lib

@ make -f ./scripts/Makefile.build obj=init这个命令为例,讲解一下详细的运行过程。可以看到这些命令运行过程其实都是一样的。再次打开scripts/Makefile.build,这个在做xxx_defconfig时已经分析过了:
image
当 只 编 译 Linux 内 核 镜 像 文 件 , 也 就 是 使 用 “ make zImage ” 编 译 的 时 候 ,KBUILD_BUILTIN=1,KBUILD_MODULES 为空。“make”命令是会编译所有的东西,包括 Linux内核镜像文件和一些模块文件。如果只编译 Linux 内核镜像的话,__build 目标简化为:
__build: $(builtin-target) $(lib-target) $(extra-y)) $(subdir-ym) $(always)
@:
重点看下builtin-target这个依赖,同样定义在scripts/Makefile.build如下:

86 ifneq ($(strip $(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)),)
87 builtin-target := $(obj)/built-in.o
88 endif

可以看到只要obj-y、obj-m、obj-、subdir-m 和 lib-target 这些变量不能全部为空,builtin-target 变量的值为:“$(obj)/built-in.o”, 这就是这些 built-in.o 的来源了。我们以@ make -f ./scripts/Makefile.build obj=init这个命令为例:
那么现在开始编译:
builtin-target := init/built-in.o

image

目标builtin-target依赖为 obj-y,命令为$(call if_changed,link_o_target),也就是调用函数 if_changed,参数为 link_o_target,其返回值就是具体的命令。前面讲过了if_changed uboot顶层makefile-2编译过程
image

它会调用 cmd_$(1)所对应的命令($(1)就是函数的第 1 个参数),因此这里就是调用:
cmd_link_o_target,也就是:

331 cmd_link_o_target = $(if $(strip $(obj-y)),\
	332 $(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^) \
	333 $(cmd_secanalysis),\
	334 rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) $@)

cmd_link_o_target 就是使用 LD将某个目录下的所有.o 文件链接在一起,最终形成 built-in.o。
命令会记录到.built-in.o.cmd:

cmd_init/built-in.o :=  arm-linux-gnueabihf-ld -EL    -r -o init/built-in.o init/main.o init/version.o init/mounts.o init/initramfs.o init/calibrate.o init/init_task.o

同理,其他的依赖项built-in.o也是同样的方式编译。至此vmlinux就产生编译完了。

1.2 make zImage过程

当我们输入:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all会编译vmlinux, zImage,然后再编译dtb,编译ko。

1.2.1 vmlinux、Image,zImage、uImage 的区别

①、vmlinux 是编译出来的最原始的内核文件,是未压缩的,比如正点原子提供的 Linux 源码编译出来的 vmlinux 差不多有 16MB。

$ ls -lh vmlinux
-rwxrwxr-x 1 robin.lee robin.lee 17M 1月  29 16:26 vmlinux

②、Image 是 Linux 内核镜像文件,但是 Image 仅包含可执行的二进制数据。Image 就是使用 objcopy 取消掉 vmlinux 中的一些其他信息,比如符号表什么的。但是 Image 是没有压缩过的,Image 保存在 arch/arm/boot 目录下,其大小大概在 12MB 左右。

$ ls -lh arch/arm/boot/Image
-rwxrwxr-x 1 robin.lee robin.lee 13M 1月  29 16:26 arch/arm/boot/Image

③、zImage 是经过 gzip 压缩后的 Image,经过压缩以后其大小大概在 6MB 左右。

$ ls -lh arch/arm/boot/zImage
-rwxrwxr-x 1 robin.lee robin.lee 6.5M 1月  29 16:26 arch/arm/boot/zImage

④、uImage 是老版本 uboot 专用的镜像文件,uImag 是在 zImage 前面加了一个长度为 64字节的“头”,这个头信息描述了该镜像文件的类型、加载位置、生成时间、大小等信息。但是新的 uboot 已经支持了 zImage 启动!所以已经很少用到 uImage 了,除非你用的很古老的 uboot。

使用“make”、“make all”、“make zImage”都可以编译出zImage, arch/arm/Makefile 中有如下代码:
image
all依赖$(KBUILD_IMAGE) $(KBUILD_DTBS), KBUILD_IMAGE为zImage, KBUILD_DTBS为dtbs。

$(BOOT_TARGETS): vmlinux
		$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@

可以看到当vmlinux产生后,就会去继续产生zImage, 展开:
@ make -f ./scripts/Makefile.build obj=arch/arm/boot MACHINE=arch/arm/boot/zImage
可以看到又是通过scripts/Makefile.build来完成的编译。

rm Image zImage
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- Image V=1
Image生成过程
make -f ./scripts/Makefile.build obj=arch/arm/boot MACHINE= arch/arm/boot/Image
  arm-linux-gnueabihf-objcopy -O binary -R .comment -S  vmlinux arch/arm/boot/Image
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage V=1
zImage生成过程
make -f ./scripts/Makefile.build obj=arch/arm/boot MACHINE= arch/arm/boot/zImage
make -f ./scripts/Makefile.build obj=arch/arm/boot/compressed arch/arm/boot/compressed/vmlinux
  (cat arch/arm/boot/compressed/../Image | lzop -9 && printf \000\100\303\000) > arch/arm/boot/compressed/piggy.lzo || (rm -f arch/arm/boot/compressed/piggy.lzo ; false)
  arm-linux-gnueabihf-gcc -Wp,-MD,arch/arm/boot/compressed/.piggy.lzo.o.d  -nostdinc -isystem /media/cvitek/robin.lee/my_test/study/openedv/toolchain/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/4.9.4/include -I./arch/arm/include -Iarch/arm/include/generated/uapi -Iarch/arm/include/generated  -Iinclude -I./arch/arm/include/uapi -Iarch/arm/include/generated/uapi -I./include/uapi -Iinclude/generated/uapi -include ./include/linux/kconfig.h -D__KERNEL__ -mlittle-endian   -D__ASSEMBLY__ -mabi=aapcs-linux -mno-thumb-interwork -mfpu=vfp -funwind-tables -marm -D__LINUX_ARM_ARCH__=7 -march=armv7-a  -include asm/unified.h -msoft-float -DCC_HAVE_ASM_GOTO        -DZIMAGE     -c -o arch/arm/boot/compressed/piggy.lzo.o arch/arm/boot/compressed/piggy.lzo.S
  arm-linux-gnueabihf-ld -EL    --defsym _kernel_bss_size=463520 -p --no-undefined -X -T arch/arm/boot/compressed/vmlinux.lds arch/arm/boot/compressed/head.o arch/arm/boot/compressed/piggy.lzo.o arch/arm/boot/compressed/misc.o arch/arm/boot/compressed/decompress.o arch/arm/boot/compressed/string.o arch/arm/boot/compressed/hyp-stub.o arch/arm/boot/compressed/lib1funcs.o arch/arm/boot/compressed/ashldi3.o arch/arm/boot/compressed/bswapsdi2.o -o arch/arm/boot/compressed/vmlinux
  arm-linux-gnueabihf-objcopy -O binary -R .comment -S  arch/arm/boot/compressed/vmlinux arch/arm/boot/zImage

标签:built,Makefile,make,makefile,vmlinux,内核,linux,arch,arm
From: https://www.cnblogs.com/fuzidage/p/17987661

相关文章

  • linux的初步认识
    Linux,一般指GNU/Linux(单独的Linux内核并不可直接使用,一般搭配GNU套件,故得此称呼),是一种免费使用和自由传播的类UNIX操作系统,其内核由林纳斯·本纳第克特·托瓦兹(LinusBenedictTorvalds)于1991年10月5日首次发布,它主要受到Minix和Unix思想的启发,是一个基于POSIX的多用户、多任务、......
  • Linux C实现在线检测
    通过ping某个服务器,检测设备是否internet是联通的。#include<stdio.h>#include<stdlib.h>#include<string.h>#include<stdbool.h>#include<unistd.h>#include<fcntl.h>#definedbg(fmt,args...)printf("\033[1m[%s]%03d:"f......
  • Linux C语言 检测IP冲突
    分析一个基于C语言实现的IP冲突检测工具。#include<stdio.h>#include<stdlib.h>#include<string.h>#include<stdbool.h>#include<getopt.h>#include<arpa/inet.h>#definedbg(fmt,args...)printf("\033[1m[%s]%03d:"fmt&quo......
  • Linux如何从命令行卡死的进程中退出?
    Linux如何从命令行卡死的进程中退出?不知道大家在使用Linux的时候,会不会遇到一些命令,有可能卡顿,有可能执行时间过长(比如使用find查找某个文件),这个时候我不想继续执行这个命令了,说来惭愧,我之前一直使用Ctrl+Z去终止这个命令,今天才知道,这样有很大的问题!信号简介一个进程在运行的......
  • linux 学习总结
      ├──usr(UnixSystemResources)等同于C:/Windows├──src系统级的源码目录├──bin用于存放用户可执行的二进制文件├──lib存放共享库文件和一些系统级别的函数库等同于C:/Windows/System32├──local用于......
  • Fortify Static Code Analyzer 23.2 for macOS, Linux & Windows - 静态应用安全测试
    FortifyStaticCodeAnalyzer23.2formacOS,Linux&Windows-静态应用安全测试FortifySCA-代码漏洞扫描工具|静态代码测试|代码安全分析请访问原文链接:https://sysin.org/blog/fortify-static-code-analyzer/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.o......
  • 通过LINUX驱动控制FPGA端PWM外设(LED) 通过应用程序命令传参随意修改寄存器的值(PWM波频
    用法:先下发下面的命令让kernel信息打印到串口:echo7417>/proc/sys/kernel/printk然后增加程序可执行性:chmod777pwmdriver_app  先执行./pwmdriver_app/dev/pwm400000200然后执行./pwm_driver_app/dev/pwm400000200,可以发现LED[1]......
  • Linux grep命令有何作用?如何使用?
    进行Linux系统维护的时候,想要在文本中快速搜索到你需要的东西,grep命令是非常不错的选择,它主要用于查找文件里符合条件的字符串,从而节省时间、提高工作效率。那么Linux系统中grep命令如何使用?我们一起来看看详细的内容介绍。Linuxgrep命令用于查找文件里符合条件的字符串......
  • Linux磁盘管理常用的三个命令!
    在Linux系统中,如何有效地对存储空间加以使用和管理,是一项非常重要且关键的技术。而且Linux磁盘管理好坏直接关系到整个系统的性能问题,那么你知道Linux磁盘管理有哪些常用命令吗?这篇文章为大家介绍一下Linux磁盘管理常用的三个命令。Linux磁盘管理常用三个命令为df、du、fd......
  • 创建linux桌面快捷方式
    第一步在linux桌面上创建一个xx.desktop文件,如下图第二步在desktop文件中输入启动命令和参数,保存文件[DesktopEntry] Encoding=UTF-8 Name=SQLDeveloper Comment=OracleSQLDeveloper Icon=/opt/sqldeveloper/icon.png Exec=/opt/sqldeveloper/sqldeveloper.sh Term......