ls背后发生了什么 Down the 'ls' Rabbit Hole

【原创】centos7 64位 安装rar和unrar 【原创】centos7 64位 安装rar和unrar作者 钱亦欣键人最近手头有个很大的压缩包,里面是一些jupyter notebook和大量的数据文件。出于少占用本机资源的目的,我打算把这个文件放到我的服务器上解压,直接用服务器端的jupyter来查看。之后问题就来了,这个压缩包是rar格式,liunx (我用的centos 7) 原生不支持解压,那么共有两种方式满足我的需求:1.在服务器上安装 阅读详情

This article was written by Adam Fletcher (@adamfblahblah)

FROM LS(1) TO THE KERNEL AND BACK AGAIN.

Too often sysadmins are afraid to dive into the source code of our core utilities to see how they really work. We're happy to edit our scripts but we don't do the same with our command line utilities, libraries, and kernel. Today we're going to do some source diving in those core components. We'll answer the age-old interview question, "What happens when you type ls at the command line and press enter?" The answer to this question has infinite depth, so I'll leave out some detail, but I'll capture the essence of what is going, and I'll show the source in each component as we go. The pedants in the crowd may find much to gripe about but hopefully they'll do so by posting further detail in the comments.

REQUIREMENTS

It'll be helpful if you install the source on your machine for the software we'll be looking at. Below are the commands I used to get the source for the needed packages on Ubuntu 9.10, and similar packages are available for your Linux distribution.

apt-get install linux-source 
apt-get source coreutils 
apt-get source bash
apt-get source libc6
apt-get install manpages-dev

I'm using linux-source version 2.6.31.22.35, coreutils (for the code to ls) version7.4-2ubuntu1, bash version 3.5.21, and libc6 version 2.10.1-0ubuntu18, and finallymanpages-dev to get the programmer's man pages.

STARTING OUT - STRACE & BASH

One of the most useful tools in the sysadmin's arsenal is strace, a command that will show you most of the standard library and system calls a program makes while it executes. We'll use this tool extensively to figure out what code we are looking for in each component.

Let's start by strace'ing bash when it runs ls. To do so, we'll start a new instance ofbash under strace. Note that I'll be cutting the output of strace down a lot in the post for readability.

adamf@kid-charlemagne:~/foo$ strace bash
execve("/bin/bash", ["bash"], [/* 30 vars */]) = 0

[... wow that's a lot of output ...]

write(2, "adamf@kid-charlemagne:~/foo$ ", 29adamf@kid-charlemagne:~/foo$ ) = 29
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
read(0,

... and that's where the output stops. If you're new to strace the key to reading it is to make liberal use of man pages to figure out what each library call does. Be aware that the relevant pages you want are in section 2 of the man pages, so you'll need to do man 2 read to find the page on read; this is because many of the system functions have the same name as regular commands that are found in chapter 1 of the man pages.

The read call is waiting for input on file descriptor 0, which is standard input. So we type ls and hit enter (you'll see more read & write calls as you type).

There's a lot of output, but we know we want to see ls related output, so let's do the simple thing and look at the lines that have ls in them:

stat("/usr/local/sbin/ls", 0x7fff03f1fd60) = -1 ENOENT (No such file or directory)
stat("/usr/local/bin/ls", 0x7fff03f1fd60) = -1 ENOENT (No such file or directory)
stat("/usr/sbin/ls", 0x7fff03f1fd60)    = -1 ENOENT (No such file or directory)
stat("/usr/bin/ls", 0x7fff03f1fd60)     = -1 ENOENT (No such file or directory)
stat("/sbin/ls", 0x7fff03f1fd60)        = -1 ENOENT (No such file or directory)
stat("/bin/ls", {st_mode=S_IFREG|0755, st_size=114032, ...}) = 0
stat("/bin/ls", {st_mode=S_IFREG|0755, st_size=114032, ...}) = 0

If we man 2 stat we see that stat returns information about a file if it can find it, and an error if it can't (much more on stat later). In this case what bash is doing is searching my $PATH environment variable in hopes of finding an executable file with the name ls. Bash will stat every directory in my $PATH, and if it can't find the file it returns command not found. In this case, Bash found ls in /bin, and then that's the last we see of the string ls in our output.

We don't see ls in our output anymore because once Bash knows it can execute the program it spawns a child process to execute that program, and we haven't told straceto follow children of the command it is tracing. It's the next few lines of strace that give this spawning away:

pipe([3, 4])                            = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f2c853217c0) = 30125

If we man 2 pipe and man 2 clone we see that bash is creating a pipe (two file descriptors that can be read and written to; this way a shell can link commands input and output together when you give the shell a | character) and clone'ing itself so that there are two copies of bash running. Remember, every UNIX process is a child of another process, and a brand new process starts out as a copy of its parent. So when does ls actually happen? Let's strace ls and find out!

adamf@kid-charlemagne:~/foo$ strace ls
execve("/bin/ls", ["ls"], [/* 30 vars */]) = 0

That first line is the key. execve is the library call to load and run a new executable. Once execve runs we're actually ls (well, the loader runs first, but that's another article). Interestingly, the call to execve is in the bash source code, not the ls source code. Let's find it in the bash code:

adamf@kid-charlemagne:/usr/src/bash-4.0/bash-4.0$ find . | xargs grep -n "execve ("
./builtins/exec.def:201:  shell_execve (command, args, env);
./execute_cmd.c:4323:   5) execve ()
./execute_cmd.c:4466:      exit (shell_execve (command, args, export_env));
./execute_cmd.c:4577:  return (shell_execve (execname, args, env));
./execute_cmd.c:4653:/* Call execve (), handling interpreting shell scripts, and handling
./execute_cmd.c:4656:shell_execve (command, args, env)
./execute_cmd.c:4665:  execve (command, args, env);

If we look at line 4323 in execute_cmd.c we see this helpful comment:

/* Execute a simple command that is hopefully defined in a disk file
somewhere.

1) fork ()
2) connect pipes
3) look up the command
4) do redirections
5) execve ()
6) If the execve failed, see if the file has executable mode set.
If so, and it isn't a directory, then execute its contents as
a shell script.
[...]
*/

And looking at line 4665 we do see the call to execve. Take a look at the code aroundexecve - it's a bunch of error handling but nothing too hard to understand. What's interesting is what is not there; the code exists only to handle errors and nothing to handle success. That is because execve will only return if there's a failure, which makes sense - a successful call to execve means we're running something completely different!

Look around execute_cmd.c at the code around calls to shell_execve and you'll see that that code is fairly straightforward.

INSIDE LS(1)

Let's look at what ls is doing by creating a single file in our directory and ls'ing that file under strace.

adamf@kid-charlemagne:~/foo$ touch bar
adamf@kid-charlemagne:~/foo$ strace ls bar
execve("/bin/ls", ["ls", "bar"], [/* 30 vars */]) = 0

Interesting! We can see that bar is now being passed to our execve call. Let's keep looking at the strace output to find bar:

stat("bar", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
lstat("bar", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f467abbe000
write(1, "bar\n", 4bar
)                    = 4

Right at the end of the strace output we see bar a few times. It looks like bar gets passed to stat, lstat, and write. Working backwards, we can man 2 write to figure out that write sends data to a file descriptor, in this case standard out, which is our screen. So the call to write is just ls printing out bar. The next two library calls, statand lstat, share a man page, with the difference between the commands being thatlstat will get information on a symbolic link while stat will only get information on a file. Let's look in in the ls source code for these calls to see why ls does both lstatand stat:

adamf@kid-charlemagne:/usr/src/coreutils-7.4/src$ grep -n "stat (" ls.c
967:      assert (0 <= stat (Name, &sb));       \ 
2437:      ? fstat (fd, &dir_stat)
2438:      : stat (name, &dir_stat)) < 0)
2721:     err = stat (absolute_name, &f->stat);
2730:         err = stat (absolute_name, &f->stat);
2749:     err = lstat (absolute_name, &f->stat);
2837:         && stat (linkname, &linkstats) == 0)

That call to lstat stands out amongst the other calls, and so it is a pretty good guess that lstat happens for some exceptional reason that programmer would notate with a comment. Looking at line 2749 in ls.c we see an interesting comment a few lines above:

         /* stat failed because of ENOENT, maybe indicating a dangling
             symlink.  Or stat succeeded, ABSOLUTE_NAME does not refer to a
             directory, and --dereference-command-line-symlink-to-dir is
             in effect.  Fall through so that we call lstat instead.  */
        }

    default: /* DEREF_NEVER */
      err = lstat (absolute_name, &f->stat);
      do_deref = false;
      break;
    }

That comment means that if we're not talking about a directory and stat has already succeeded, we need to see if we are looking at a symlink. We can see that this is true by ls'ing a directory under strace:

adamf@kid-charlemagne:~/foo$ strace ls /home/adamf/foo/
[...]
stat("/home/adamf/foo/", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
open("/home/adamf/foo/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3
fcntl(3, F_GETFD)                       = 0x1 (flags FD_CLOEXEC)
getdents(3, /* 3 entries */, 32768)     = 72
getdents(3, /* 0 entries */, 32768)     = 0
close(3)                                = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f873dda4000
write(1, "bar\n", 4bar

Note that there was no call to lstat this time.

WHERE WE ARE GOING THERE IS NO STRACE

It is time to bid our friend strace a fond farewell as he doesn't have what it takes to show us what stat is doing. For that we need to look into the standard library, or as it is commonly known, libc.

The libc code provides a common API for UNIX programs, and a portion of that API is the system calls. These are functions that provide a way for a programmer to ask the kernel for a resource that is managed by the kernel, including the resource we're interested in: the filesystem. The code we'd like to look at is for the system call stat. However, because kernels are very dependent on the hardware architecture they run on, and libc needs to talk to the kernel, much of the code you'll find in the libc source organized by architecture. This makes finding the code for stat tricky; if we look inio/stat.c we see basically a single line of code that calls a function called __xstat. If we find . -name xstat.c we'll see that we want./sysdeps/unix/sysv/linux/i386/xstat.c, which is the implementation of stat for Linux on i386.

The code in xstat.c that isn't a reference to a C #include looks like:

return INLINE_SYSCALL (stat, 2, CHECK_STRING (name), CHECK_1 ((struct kernel_stat *) buf));

And:

result = INLINE_SYSCALL (stat64, 2, CHECK_STRING (name), __ptrvalue (&buf64));

Reading the comments in the code we can see that stat64is for 64-bit platforms. We'll stick to 32-bits for now, but either way we need to figure out what INLINE_SYSCALL is. A convention in C programming is that FUNCTIONS IN ALL CAPS are pre-processor macros, which means you can typically find out what those macros are by grep'ing fordefine <macroname>:

adamf@kid-charlemagne:/usr/src/eglibc-2.10.1/sysdeps/unix/sysv/linux/i386$ grep -n "define INLINE_SYSCALL" *
sysdep.h:348:#define INLINE_SYSCALL(name, nr, args...) \

At first, the code we find at line 348 in sysdep.h looks confusing:

#define INLINE_SYSCALL(name, nr, args...) \ 
({                                                                          \ 
    unsigned int resultvar = INTERNAL_SYSCALL (name, , nr, args);             \ 
    if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (resultvar, ), 0))         \ 
    {                                                                       \ 
        __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, ));                   \ 
        resultvar = 0xffffffff;                                               \ 
    }                                                                       \ 
    (int) resultvar; })

Looking at the code the call to INTERNAL_SYSCALL stands out - it appears that allINLINE_SYSCALL is doing is calling INTERNAL_SYSCALL. Conveniently we can scroll down in sysdep.h to find the definition of INTERNAL_SYSCALL:

/* Define a macro which expands inline into the wrapper code for a system
call.  This use is for internal calls that do not need to handle errors
normally.  It will never touch errno.  This returns just what the kernel
gave back.

The _NCS variant allows non-constant syscall numbers but it is not
possible to use more than four parameters.  */
#undef INTERNAL_SYSCALL
#ifdef I386_USE_SYSENTER
# ifdef SHARED
#  define INTERNAL_SYSCALL(name, err, nr, args...) \

... but it appears to define INTERNAL_SYSCALL a few times, and I'm not sure which one is actually used.

A good practice in a situation like this is to stop looking at the code and instead take some time to understand the concept the code is trying to implement. Googling for something like i386 system calls linux gets us a to (Implementing A System Call On i386 Linux)[http://tldp.org/HOWTO/html_single/Implement-Sys-Call-Linux-2.6-i386/] which says:

A system call executes in the kernel mode. Every system call has a number
associated with it. This number is passed to the kernel and that's how the
kernel knows which system call was made. When a user program issues a system
call, it is actually calling a library routine. The library routine issues a
trap to the Linux operating system by executing INT 0x80 assembly instruction.
It also passes the system call number to the kernel using the EAX register. The
arguments of the system call are also passed to the kernel using other
registers (EBX, ECX, etc.). The kernel executes the system call and returns the
result to the user program using a register. If the system call needs to supply
the user program with large amounts of data, it will use another mechanism
(e.g., copy_to_user call).

Okay, so I think the implementation of INTERNAL_SYSCALL we'll want will have 0x80 in it and some assembly code that puts stuff in the eax register (newer x86 machines can use sysenter instead of int 0x80 to make syscalls). Line 419 in sysdep.h does the trick:

# define INTERNAL_SYSCALL(name, err, nr, args...) \ 
({                                                                          \ 
    register unsigned int resultvar;                                          \ 
    EXTRAVAR_##nr                                                             \ 
    asm volatile (                                                            \ 
    LOADARGS_##nr                                                             \ 
    "movl %1, %%eax\n\t"                                                      \ 
    "int $0x80\n\t"                                                           \ 
    RESTOREARGS_##nr                                                          \ 
    : "=a" (resultvar)                                                        \ 
    : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc");                  \ 
    (int) resultvar; })

If we go back to xstat.c we see that the name we pass to INTERNAL_SYSCALL is stat, and in the code above the name argument will expand from __NR_##name to __NR_stat. The web page we found describing syscalls says that syscalls are represented by a number, so there has to be some piece of code that turns __NR_stat into a number. However, when I grep through all of the libc6 source I can't find any definition of__NR_stat for i386.

It turns out that the code that translates __NR_stat into a number is inside the Linux kernel:

adamf@kid-charlemagne:/usr/src/linux-source-2.6.31$ find . | grep x86 | xargs grep -n "define __NR_stat"
./arch/x86/include/asm/unistd_64.h:23:#define __NR_stat             4
./arch/x86/include/asm/unistd_64.h:309:#define __NR_statfs              137
./arch/x86/include/asm/unistd_32.h:107:#define __NR_statfs       99
./arch/x86/include/asm/unistd_32.h:114:#define __NR_stat        106
./arch/x86/include/asm/unistd_32.h:203:#define __NR_stat64      195
./arch/x86/include/asm/unistd_32.h:276:#define __NR_statfs64        268

THE AMULET OF YENDOR: INSIDE THE KERNEL

The syscall number definitions being inside the kernel makes sense, as the kernel is the owner of the syscall API and as such will have the final say on what numbers get assigned to each syscall. As we're running on 32-bit Linux, it appears the syscall number that libc is going to put in eax is 106.

The table in unistd_32.h is great (look at all those syscalls!) but it doesn't tell us where the code for handling a call to stat actually lives in the kernel. find is our friend again:

adamf@kid-charlemagne:/usr/src/linux-source-2.6.31$ find . -name stat.c
./fs/stat.c
./fs/proc/stat.c

Well that was easy. Opening up fs/stat.c we find what we're looking for:

SYSCALL_DEFINE2(stat, char __user *, filename, struct __old_kernel_stat __user *, statbuf)
{
        struct kstat stat;
        int error;

        error = vfs_stat(filename, &stat);
        if (error)
                return error;

        return cp_old_stat(&stat, statbuf);
}

Looks like this just a wrapper around vfs_stat, which is also in stat.c and is a wrapper around vfs_statat, which again is in stat.c and is wrapper around two functions, user_path_at() and vfs_getattr(). We'll ignore user_path_at() for now (it figures out if the file exists) and instead follow vfs_getattr():

int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
{
        struct inode *inode = dentry->d_inode;
        int retval;

        retval = security_inode_getattr(mnt, dentry);
        if (retval)
                return retval;

        if (inode->i_op->getattr)
                return inode->i_op->getattr(mnt, dentry, stat);

        generic_fillattr(inode, stat);
        return 0;
}

One thing that is helpful to do in a case like is to look back at any documentation I have on the function whose implementation I'm tracking down, which in this case is the library call to stat. Back to man 2 stat we see:

   All of these system calls return a stat structure, which contains the following fields:

       struct stat {
           dev_t     st_dev;     /* ID of device containing file */
           ino_t     st_ino;     /* inode number */
           mode_t    st_mode;    /* protection */
           nlink_t   st_nlink;   /* number of hard links */
           uid_t     st_uid;     /* user ID of owner */
           gid_t     st_gid;     /* group ID of owner */
           dev_t     st_rdev;    /* device ID (if special file) */
           off_t     st_size;    /* total size, in bytes */
           blksize_t st_blksize; /* blocksize for file system I/O */
           blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
           time_t    st_atime;   /* time of last access */
           time_t    st_mtime;   /* time of last modification */
           time_t    st_ctime;   /* time of last status change */
       };

So our vfs_getattr function is trying to fill out these fields, which must be in thestruct kstat *stat argument to vfs_getattr. vfs_getattr tries to fill out the statstruct in two ways:

    if (inode->i_op->getattr)
            return inode->i_op->getattr(mnt, dentry, stat);

    generic_fillattr(inode, stat);

In the first attempt to fill stat, vfs_getattr checks to see if this inode struct has a special function defined to fill the stat structure. Each inode has an i_op struct which can have a getattr function, if needed. This getattr function is not defined in fs.hbut rather is defined by the specific file system the inode is on. This makes good sense as it allows the application programmer to call libc's stat without caring if the underlying file system is ext2, ext3, NTFS, NFS, etc. This abstraction layer is called the 'Virtual File System' and is why the syscall above is prefixed with 'vfs'.

Some filesystems, like NFS, implement a specific getattr handler, but the filesystem I'm running (ext3) does not. In the case where there is no special getattr function defined vfs_getattr will call generic_fillattr (helpfully defined in stat.c) which simply copies the relevant data from the inode struct to the stat struct:

void generic_fillattr(struct inode *inode, struct kstat *stat)
{
        stat->dev = inode->i_sb->s_dev;
        stat->ino = inode->i_ino;
        stat->mode = inode->i_mode;
        stat->nlink = inode->i_nlink;
        stat->uid = inode->i_uid;
        stat->gid = inode->i_gid;
        stat->rdev = inode->i_rdev;
        stat->atime = inode->i_atime;
        stat->mtime = inode->i_mtime;
        stat->ctime = inode->i_ctime;
        stat->size = i_size_read(inode);
        stat->blocks = inode->i_blocks;
        stat->blksize = (1 << inode->i_blkbits);
}

If you squint a little bit at this struct you'll see all the fields you can get out of a singlels command! Our adventure into the kernel has yielded fruit.

JUST ONE MORE TURN...

If you'd like to keep going, the next thing to figure out is how the inode struct gets populated (hint: ext3_iget) and updated, and from there figure out how the kernel reads that data from the block device (and then how the block device talks to the disk controller, and how the disk controller finds the data on the disk, and so on).

I hope this has been instructive. Digging through the actual source code to a program isn't as easy as reading a summary of how something works, but it is more rewarding and you'll know how the program actually works. Don't be intimidated by an unknown language or concept! We found our way through the internals of the kernel with strace,find and grep, tools a sysadmin uses every day.

OTHER RESOURCES


http://sysadvent.blogspot.com/2010/12/day-15-down-ls-rabbit-hole.html



Kali Linux实战:Aircrack-ng破解Wi-Fi密码的完整流程与常见问题解决 本文详细介绍了在Kali Linux中使用Aircrack-ng套件进行Wi-Fi密码破解的完整流程,包括环境准备、无线网卡配置、网络扫描、握手包捕获与字典破解等关键步骤。同时针对无线网卡不支持监听模式、无法捕获握手包等常见问题提供了实用解决方案,帮助安全研究人员有效评估无线网络安全性。 阅读详情

相关推荐

处理图数据, 安装“Pytorch“ + 图神经网络开源框架“PyG “+ “ogb“使用

"OGB" OSError: [WinError 127] 找不到指定的程序。1.[遇到这类问题往往跟torch安装的工具包(如torch-sparse,torch-scatter,torch-cluster)版本没对应上有关](https://blog.youkuaiyun.com/weixin_42358688/article/details/117433691)2.[OGB使用环境安装与依赖](https://ogb.stanford.edu/docs/home/)Data Loaders3.[torch-geo

Fuguir™的博客 3698

ls官方源代码

/* `dir', `vdir' and `ls' directory listing programs for GNU. Copyright (C) 85, 88, 90, 91, 1995-2003 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public

xuchaoxin1375的博客 2286

告别Link180!在Ansys Mechanical 2020R2中正确启用Cable280绳索单元(附Beta选项开启指南)

本文详细介绍了在Ansys Mechanical 2020R2中启用Cable280绳索单元的全过程,包括Beta选项的开启步骤、建模技巧及高阶应用。Cable280作为专为绳索仿真设计的单元,相比传统的Link180单元,在大变形模拟和计算效率上表现更优,特别适合斜拉桥、电梯牵引绳等工程场景。

weixin_33711647的博客 405

控制信号brk_Linux进程控制--STRACE:追踪信号和系统调用

在传统的UNIX系统上,判断一个进程实际正在做什么相当困难,用户只有根据从文件系统以及ps这样的工具取得的间接数据和经验来推测,而在Linux中,用户可以通过strace命令直接观察一个进程,进程的每一次系统调用,每接收到一个信号,这个命令都能显示出来。用户还可以把strace附在一个正在执行的进程上,监视一会儿该进程,再从进程上脱离,整个过程都不会影响那个进程。[root@www.linuxid...

weixin_39658019的博客 343

PX4无人机-Gazebo仿真实现动态目标追踪的视觉控制方案

本文详细介绍了PX4无人机在Gazebo仿真环境中实现动态目标追踪的视觉控制方案。从PX4与Gazebo仿真环境搭建、动态目标追踪核心技术栈、仿真环境深度定制技巧到追踪算法的优化实践,提供了全面的技术指导和常见问题排查方法,帮助开发者高效实现无人机视觉追踪功能。

weixin_29196315的博客 450

[网络安全自学篇] 二.Chrome浏览器保留密码功能渗透解析及登录加密入门笔记

最近开始学习网络安全相关知识,接触了好多新术语,感觉自己要学习的东西太多,真是学无止境,也发现了好几个默默无闻写着博客、做着开源的大神。接下来系统分享一些网络安全的自学笔记,希望读者们喜欢。 上一篇文章分享了看雪Web安全总结知识和一个异或解密的示例,本篇文章着重讲解Chrome浏览器保留密码功能渗透解析及登录加密入门笔记,结合实际例子一步步实现浏览器漏洞的挖掘。非常基础的文章,希望对入门的博友们有帮助,大神请飘过,谢谢各位看官!

杨秀璋的专栏 2万+

Jetson无法开机卡not writing throught dangling symlink ‘etc/resol

大部分进不了图形窗口环境的都是因为文件系统写满了。

weixin_48695448的博客 6442

非洲秃鹫优化算法(AVOA)详解:从原理到实战

非洲秃鹫优化算法(AVOA)是一种模拟秃鹫觅食行为的元启发式算法。该算法通过数学建模秃鹫的群体分工、饥饿感知和食物竞争等行为,将优化问题转化为智能觅食过程。AVOA包含四个关键阶段:(1)种群初始化与最佳秃鹫选择;(2)饥饿率控制探索与开发平衡;(3)探索阶段模拟远距离飞行搜索;(4)开发阶段模拟食物源附近的竞争行为。算法采用饥饿率函数实现自适应搜索,初期偏向全局探索,后期转向局部开发。实验表明AVOA在标准测试函数和工程设计问题上表现出优越性能,其创新性在于将秃鹫独特的生物学特性转化为高效的优化机制。

qq_42212808的博客 227

Jetson nano无法开机,出现cp:not writing throught dangling symlink ‘etc/resolv.conf‘

Jetson nano无法开机,出现cp:not writing throught dangling symlink ‘etc/resolv.conf'

SUDA196的博客 6294

用一张分析型 CDS Query 看清争议案件新增与结案节奏:C_OpenClosedDisputeCase 深度解读

应收账款争议管理中的关键CDS视图分析 摘要:C_OpenClosedDisputeCase是SAP系统中用于监控应收账款争议案件的重要CDS视图,提供三个时间窗口(当日、近5天、当月)的新增与结案数据。该视图通过"创建vs解决"的净变化指标,帮助财务团队实时掌握争议管理趋势,特别适用于多币种跨国企业的现金流管理。其核心价值在于将争议管理从被动"救火"转变为可量化运营,通过统一汇率换算和关键日期参数,为管理层提供标准化的运营仪表盘。视图采用特权访问模式,需通过上层应用

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 122

Pixhawk2.4.8接口及引脚定义

pixhawk2.4.8接口定义图解

加斯顿工程师的博客 8745

在shell中键入ls l会发生什么

We came across ls in a previous article when we explained “ What happens when you type ls *.c”. However in this article we’re going to explain what really happens when you type ls- l. 我们在前面的文章中碰到LS当我们...

weixin_26755331的博客 588

MATLAB与ROS联合仿真——实例程序搭建思路

MATLAB与ROS联合仿真——实例程序搭建思路

慕羽★的博客 5228

shell脚本执行过程

一、先看一个简单的脚本执行过程 shell脚本中以#表示注释。但是如果#位于第一行并且后面是感叹号,它表示该脚本使用后面指定的解释器解释执行。#!/bin/bash叫做shebang,它指定了解释器。 因为编写好的shell脚本文件是一个普通文本文件,所以我们要对它赋予可执行权限才可以执行。或者直接使用解释器对文本文件进行解释执行。 二、shell的执行过程 1、

Sunnylunch-blog 1万+

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

C语言实现Linux ls命令

C 语言实现 Linux ls 命令 ls 常用参数: -l:以长格式显示目录下的内容列表。输出的信息从左到右依次包括文件名,文件类型、权限模式、硬连接数、所有者、组、文件大小和文件的最后修改时间等;-a:显示所有档案及目录;-r:以文件名反序排列并输出目录内容列表;-t:用文件和目录的更改时间排序;-R:递归处理,将指定目录下的所有文件及子目录一并处理;-r:以文件名反序排列并输出目录内...

git1314的博客 3150

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Linux系统的命令源代码的获取方法

我们知道,Linux是开源的,它自带的功能强大的命令也是开源的,也就是说,我们可以获得这些命令的源代码并研究它。那究竟如何获得系统的命令的源代码呢?命令的源代码是一个软件包为单元的,放在一个软件包的源代码中,若要下载一个命令的源代码,就要把这个命令所属的软件包的源代码都下载下来。命令的源代码就在下载的源代码的相关目录内,通常是src目录,相应的主文件名为cmd.c,其中cmd为具体的命令,如ls命

ljianhui的专栏 2万+

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

玲珑学院OJ 1132 Down the Rabbit Hole【Dfs序+暴力】

1132 - Down the Rabbit Hole Time Limit:1s Memory Limit:512MByte Submissions:135Solved:54 DESCRIPTION 5.632 我(或者是在读这篇文字的你)不属于这个世界 这是世界的界限 6.41 世界的意义必定存在于世界之外 世界中的一切事物如其所存在般

mengxiang000000 598

centos7下安装

安装rar的步骤还挺麻烦的,不过顺藤摸瓜也就一个一个都安装好了 首先进入root 安装wget yum -y install wget 然后才能用wget指令 wget http://www.rarlab.com/rar/rarlinux-x64-5.6.1.tar.gz 我去官网看了最新版本是5.6.1 下载好了后会是一个压缩文件,直接解压 tar -xzvf rarlinux-x64-5.3....

From zero 3799

Linux命令执行过程

在 Linux 系统中“一切皆文件”,Linux 命令也不例外。那么,当编辑完成 Linux 命令并回车后,系统底层到底发生了什么事情呢? 简单来说,Linux 命令的执行过程分为如下 4 个步骤。 1) 判断路径 判断用户是否以绝对路径或相对路径的方式输入命令(如 /bin/ls),如果是的话直接执行。 2) 检查别名 Linux 系统会检查用户输入的命令是否为“别名命令”。要知道,通过...

u010783226的专栏 487

RabbitMQ思维导图

RabbitMQ消息中间件高可用方案 RabbitMQ 原理图 rabbitMQ的整体逻辑图 基于RabbitMQ的即时通讯模型 RabbitMQ

极客神殿 1469

docker容器内时间与服务器时间不一致解决办法

docker容器内时间与服务器时间差距8小时,因为原生docker是0时区,但我们服务器采用亚洲上海东八区。先进入docker容器 docker exec -it 容器ID /bin/bash 1、复制上海时区至/etc/localtime cp -i /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 但是报错如下: cp: not writing through dangling symlink '/etc/localtime' 看报.

风清痕迹 8428

查找linux command source code

# rpm -qif `which sort`Name        : coreutils                    Relocations: (not relocatable)Version     : 5.2.1                             Vendor: CentOSRelease     : 31.4                          Build Date: Sun 13 Aug 2006 10:26:34 AM GMTInstall Dat

rocky2com的专栏 1672

vsftpd ftp client ls command implementation source code

#include #include #include #include #include #include #include #include #include struct sockaddr_in ftp_server; int sock_control; int sock_data; struct timeval outtime; int ret; char

烟台 嵌入式产品开发 772

Linux执行ls,会引起哪些系统调用

可以通过strace -o ls.txt ls进行查看: open(".", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 3 ///打开当前目录这个文件(目录是一种特殊的文件),并返回文件句柄3 fstat64(3, {st_mode=S_IFDIR|0755, st_size=4096, }) = 0   ///取得当

不忘初心,方得始终 4550

MAC OSX下查看某个端口被哪个程序占用及杀进程方法

sudo lsof -i : 9000COMMAND   PID    USER   FD   TYPE             DEVICE SIZE/OFF NODE NAMEjava    61342 a  313u  IPv6 0x1111111111111     0t0  TCP *:cslistener (LISTEN)然后根据PID杀进程:sudo kill -9 61342

1万+

MAC OSX 中解决编译“'cc' failed with exit status 1”错误 和clang: error: unknown argument 错误

错误例子:error: command 'cc' failed with exit status 1clang: error: unknown argument: '-multiply_definedsuppress' [-Wunused-command-line-argument-hard-error-in-future] clang: note: this will be a hard err

1万+
上一篇: 如何提升网站性能 Website Performance Optimization
下一篇: Mergesort
chiiis
博客等级 码龄14年 422粉丝 429原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值