additional applets available as ash builtins?

Cristian Ionescu-Idbohrn cristian.ionescu-idbohrn at axis.com
Sat Apr 12 20:13:50 UTC 2008


Great.  Thanks a lot fo the information.

On Sat, 12 Apr 2008, Denys Vlasenko wrote:

> There are special subsets of applets called NOFORK and NOEXEC applets:
>
> # grep '^U.*NOFORK' include/applets.h

...

> # grep '^U.*NOEXEC' include/applets.h

...

> From your list above, kill is already a builtin,

Hmm... I don't see it.  include/applets.h says:

  USE_KILL(APPLET(kill, _BB_DIR_BIN, _BB_SUID_NEVER))

meaning kill isn't a NOFORK/NOEXEC applet?

Yes, shell/ash.c calls these:

        return kill_main(argc, argv);
        return echo_main(argc, argv);
        return test_main(argc, argv);

> and many others are NOFORK or NOEXEC applets. TO be exact:
> * NOEXEC applets: cut ln
> * Ordinary applets: date env expr head mktemp pgrep pidof pkill printf
>   readlink realpath stat tail uniq wc which
> * The rest are NOFORK.
>
> With CONFIG_FEATURE_PREFER_APPLETS=y and CONFIG_FEATURE_SH_STANDALONE=y,
> NOFORK and NOEXEC applets will be run by ash without using exec() call
> (rm is NOFORK):
>
> # touch TEST
> # strace -ff ./busybox ash -c 'rm TEST'

...

> BTW, I actually expected that it will not even fork()... need to take a
> look.

Yes.  I also see some forking there:

# strace -ff -tt -e trace=process ./busybox ash -c 'touch /tmp/foo'
21:38:17.411346 execve("./busybox", ["./busybox", "ash", "-c", "touch
/tmp/foo"], [/* 55 vars */]) = 0
21:38:17.413804 clone(Process 5859 attached
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,
child_tidptr=0xb7dab6f8) = 5859
[pid  5858] 21:38:17.414019 waitpid(-1, Process 5858 suspended
 <unfinished ...>
[pid  5859] 21:38:17.415039 exit_group(0) = ?
Process 5858 resumed
Process 5859 detached
21:38:17.415191 <... waitpid resumed> [{WIFEXITED(s) && WEXITSTATUS(s) ==
0}], 0) = 5859
21:38:17.415230 --- SIGCHLD (Child exited) @ 0 (0) ---
21:38:17.415296 exit_group(0)           = ?
Process 5858 detached

> Anyway. The best way for you to make these applets run faster is to make
> them NOFORK. It is not awfully difficult, just nobody wanted to invest
> his timein doing it.
>
> Read docs/nofork_noexec.txt

Thanks for the explanation.  I knew there was something I missed.  So the
key to better shell performance would be enabling:

  FEATURE_SH_STANDALONE
	This option causes busybox shells to use busybox applets
	in preference to executables in the PATH whenever possible.  For
	example, entering the command 'ifconfig' into the shell would cause
	busybox to use the ifconfig busybox applet.  Specifying the fully
	qualified executable name, such as '/sbin/ifconfig' will still
	execute the /sbin/ifconfig executable on the filesystem.

which also enables:

  FEATURE_PREFER_APPLETS
	This is an experimental option which directs applets about to
	call 'exec' to try and find an applicable busybox applet before
	searching the PATH. This is typically done by exec'ing
	/proc/self/exe.

And then expect faster execution of applets located with:

  # egrep '^U.*NO(EXEC|FORK)' include/applets.h | \
  cut -d'(' -f3 | cut -d, -f2 | tr ' ' '\t' | sort
        awk
        basename
        cat
        chgrp
        chmod
        chown
        cp
        cut
        dd
        dirname
        echo
        false
        find
        hexdump
        hostid
        length
        ln
        logname
        ls
        mkdir
        pwd
        rm
        rmdir
        seq
        sleep
        sort
        sync
        tac
        test
        test
        touch
        true
        usleep
        whoami
        xargs
        yes

That means these applets:

	date
	env
	expr
	head
	kill
	mktemp
	pgrep
	pidof
	pkill
	printf
	readlink
	realpath
	stat
	tail
	uniq
	wc
	which

could be NO(EXEC|FORK) candidates.

Cheers,

-- 
Cristian



More information about the busybox mailing list