[Application] Porting Linux application to NuttX

588 views
Skip to first unread message

jscc...@gmail.com

unread,
Jul 19, 2018, 3:07:36 AM7/19/18
to NuttX
Hi,

Since a very attractive advantage of NuttX is POSIX/ANSI standard compatible,
we are trying to port widely used application in Linux to see NuttX compatibility.
Currently, we choose an Linux network application which is called "iPerf".
To build the iPerf in NuttX, we have some "undefined reference" error.
It is because of NuttX is lack of some "system call" or "libc" functions.

for system call, such as:
iperf3_main.c:(.text+0x14): undefined reference to `setjmp'
iperf3_main.c:(.text+0x148): undefined reference to `longjmp'
iperf_api.c:(.text+0x3538): undefined reference to `getpeername'

for lib functions, such as:
iperf_util.c:(.text+0x24): undefined reference to `srandom'
iperf_util.c:(.text+0x48): undefined reference to `random'

Could you give us suggestions how to solve these issue?
If you suggest us to port these functions, could you give us some hint or resource for the best way to port?
If we want to port system call "getpeername()" or libc function "random()",
could you give us an example how you port system call "getsockname()" or libc function "rand()"?

Thanks in advance.

BRs,
Jesse

Xang Xiao

unread,
Jul 19, 2018, 5:51:56 AM7/19/18
to NuttX

Jesse,

For getpeername case, we have made an implementation several months ago in our private git.

If you want, we could upstream the implementation as a demo how to add new syscall for NuttX.

 

Thanks

Xiang

jscc...@gmail.com

unread,
Jul 19, 2018, 6:13:19 AM7/19/18
to NuttX
Hi Xiang,

I really appreciate your generous help. Please tell me how to get your getpeername implementation.
And may I know what resource do you reference for your getpeername code? I'd like to try to implement more syscall.
Thanks.

BRs,
Jesse

Xang Xiao於 2018年7月19日星期四 UTC+8下午5時51分56秒寫道:

Xang Xiao

unread,
Jul 19, 2018, 6:42:58 AM7/19/18
to NuttX
I will post the patch for review by end of today, please wait a moment.
Since getpeername isn't difficult to implement,  reading NuttX's network stack code is enough to finish the work.
For srandom/random/rand, NuttX has already provided the implementation, please reference:
crypto/random_pool.c
libs/libc/stdlib/lib_rand.c
libs/libc/stdlib/lib_srand.c

Thanks
Xiang

patacongo

unread,
Jul 19, 2018, 9:05:15 AM7/19/18
to NuttX
Finally, these


iperf3_main.c:(.text+0x14): undefined reference to `setjmp'
iperf3_main.c:(.text+0x148): undefined reference to `longjmp'


These are not provided by NuttX.  Your toolchain needs to provided these view setjmp.h.  Normally that happens automatically.

There are places in README files where it recommends using -nostdinc with GCC to avoid picking up incompatible header files from newlib.  However, there are a couple of files that you need to get from the compiler:  setjmp.h and vararg.h come to mind.  These are tied into the way that the compiler does things so the compiler is the ultimate source.

So if these header files are needed, then -nostdinc is a bad idea because it will prevent you from including them.  I suspect that you have -nostdinc set in your CFLAGS.  If you remove the argument from the CFLAGS, then the compiler should be able to finds its setjmp.h header file.

patacongo

unread,
Jul 19, 2018, 1:22:38 PM7/19/18
to NuttX
FYI

commit 58bbb664811aa921f44fc9af01ec5b7a60294b42
Author: Gregory Nutt <gn...@nuttx.org>
Date:   Thu Jul 19 11:21:49 2018 -0600

    libs/libc/stdlib and include/stdlib.h:  Add implementation of random() and srandom().


jscc...@gmail.com

unread,
Jul 20, 2018, 3:04:44 AM7/20/18
to NuttX
Hi Greg,

Thanks for your reply. I've checked my CFLAGS. It does not contain -nostdinc.
And I've tried to link setjmp/longjmp from toolchain. Here are my steps:

1. arm-none-eabi-gcc -print-file-name=libc.a
2. arm-none-eabi-ar -xv libc.a lib_a-setjmp.o
3. cp lib_a-setjmp.o nuttx/libc
4. let lib_a-setjmp archived in nuttx/libc/libc.a

Then 'undefined reference setjmp/longjmp' errors are gone.

BRs,
Jesse

patacongo於 2018年7月19日星期四 UTC+8下午9時05分15秒寫道:

jscc...@gmail.com

unread,
Jul 20, 2018, 3:26:44 AM7/20/18
to NuttX
Hi Xiang and Greg,

Thanks for your help. These answers make me solve most of my linking errors.
Originally, I would like to know the method how to implement un-existing functions so I did not list all my linking errors.
Now I know one reference is NuttX source code. Is there any external reference you usually preferred?
And there are still some 'undefined reference' of missing libc functions.
How do you suggest me to solve these error?

iperf3_main.c:(.text+0x4c): undefined reference to `daemon'
iperf_api.c:(.text+0xbf8): undefined reference to `getopt_long'
iperf_util.c:(.text+0x300): undefined reference to `clock'
iperf_error.c:(.text+0x8b4): undefined reference to `hstrerror'

Hope these questions will not bother you too much.

BRs,
Jesse

patacongo於 2018年7月20日星期五 UTC+8上午1時22分38秒寫道:

Xang Xiao

unread,
Jul 20, 2018, 4:23:51 AM7/20/18
to NuttX
hstrerror is obsolete(https://linux.die.net/man/3/hstrerror), 
it's better to call gai_strerror instead which was added to NuttX recently:
libs/libc/netdb/lib_gaistrerror.c
clock is also supported recently, can't understand why you hit this linker error:
libs/libc/time/lib_clock.c 

As far as I know, NuttX doesn't support daemon yet,
but you can simulate daemon easily by spawn a background task manually.
You can reference many NuttX's daemon soure code, e.g.:
apps/system/stackmonitor/stackmonitor.c

jscc...@gmail.com

unread,
Jul 20, 2018, 5:06:52 AM7/20/18
to NuttX
Hi Xiang,

Thanks for your reply.
The cause of lost clock() is I use nuttx-7.24.
After sync to the latest version,
I've found clock() in sched/clock/clock.c.

BRs,
Jesse

Xang Xiao於 2018年7月20日星期五 UTC+8下午4時23分51秒寫道:

Gregory Nutt

unread,
Jul 20, 2018, 9:23:16 AM7/20/18
to nu...@googlegroups.com
We should be clear that we are not talking about operating system interfaces here, we are talking about C libary interfaces.  Most C libraries support and inconsistent set of non-standard interfaces (the NuttX C library is not an exeption to this rule).


As far as I know, NuttX doesn't support daemon yet,
but you can simulate daemon easily by spawn a background task manually.
You can reference many NuttX's daemon soure code, e.g.:
apps/system/stackmonitor/stackmonitor.c

daemon() is a non-standard Linux interface.  The interfaces defined at OpenGroup.org are the interfaces that govern NuttX.  deamon() is only described in the Linux man pages like:  http://man7.org/linux/man-pages/man3/daemon.3.html

It is not possible to support a true Linux daemon() helper function because it is designed to work only in the Linux environment and cannot be translated to NuttX.  The above mentioned web page states:
       The daemon() function is for programs wishing to detach themselves
       from the controlling terminal and run in the background as system
       daemons.

NuttX does not support controlling terminals, nor does any other embedded RTOS that I am aware of.

       If nochdir is zero, daemon() changes the process's current working
       directory to the root directory ("/"); otherwise, the current working
       directory is left unchanged.

       If noclose is zero, daemon() redirects standard input, standard
       output and standard error to /dev/null; otherwise, no changes are
       made to these file descriptors.
These two features could be supported, but are not so interesting.

But the basic operation of a NuttX daemon() variant could not be supported because it relies on a true fork() operation.  From the above reference:
       (This function forks, and if the fork(2) succeeds, the parent calls
       _exit(2), so that further errors are seen by the child only.)  ...
fork() requires to an MMU.  There is way to fork in a truly embedded system that has no MMU.  uClinux can't fork either (http://nommu.org/).  Both uClinux and NuttX support vfork(), but vfork() cannot be used as a direct substitute for fork() in this case.

Greg


patacongo

unread,
Jul 20, 2018, 9:58:13 AM7/20/18
to NuttX
Having said all of that, here is a crippled version of daemon() with will probably meet the porting need in most cases:

commit 5a894597830afe559264839b23a5ada4282417fd
Author: Gregory Nutt <gn...@nuttx.org>
Date:   Fri Jul 20 07:56:09 2018 -0600

    libs/libc/unistd/:  Add a crippled version of daemon().


It does not do very much, but then what could you expect with no fork()?

Greg

patacongo

unread,
Jul 20, 2018, 10:11:51 AM7/20/18
to NuttX
It is probably work blabbering a bit about what is meant by a "non-standard" interface.

The POSIX standard was created to define a portable standard operating system interface.  In fact, that is what the P in POSIX stands for (Portable Operating System Interface for Unix). So, provided that you adhere to the standard, portable inteface definitions (of say, OpenGroup.org), then your code will be portable.  You can take the code from one POSIX system and run it on a another POSIX system with no substantial change.

Whenever you use a non-standard interface, such as daemon(), then your code it no longer portable.  It cannot be moved from one OS environment to another without modifying the code.

I did just add a "plug" for the daemon() interface, but I probably should not have done that.  That propagates the non-standard interfaces.

When you run into a undefined inteface, say zyz,  in complling code for another OS.  First, you must decide if that is a standard, portable interface or not.  You can determine if it is "standard" by doing something like googling for "xyz site:OpenGroup.org".  If the interface is defined at Opengroup.org, then it makes since to ping the OS developer about his/her missing standard interfaces.

If does not appear at OpenGroup.org, then it is a non-standard interface.  In this case, it is worth discussing here but in general, you should plan to modify the code that you are porting so that it does use only standard interfaces.  The error is in the application that uses the non-portable interfaces, not in the OS that provides the portable interfaces.

Greg

patacongo

unread,
Jul 20, 2018, 10:18:27 AM7/20/18
to NuttX
getopt_long() and hstrerror() are also in this category.  They are not portable interfaces.  hstrerror is also obsolete (and it can simply be replaces with strerror).

getopt_long() is non-standard, but it seems could be useful.  Unfortunately, it is a lot of programming effort to implement this non-standard interface.  I don't care enough to implement it, but if someone else is sufficiently motivated, I would accept the contribution.

Greg


jscc...@gmail.com

unread,
Jul 22, 2018, 11:02:17 PM7/22/18
to NuttX
Hi Greg,

Thanks for your help and very clear explanation.
For the next time I find a missing API, I'll check if it's standard or not.
If it is not standard, I'll try to implement it myself first.
And if this non-standard interface is useful, I'll discuss this with you if this can be shared in NuttX.

BRs,
Jesse

patacongo於 2018年7月20日星期五 UTC+8下午10時18分27秒寫道:

xiang xiao

unread,
Sep 18, 2018, 11:22:37 PM9/18/18
to NuttX, jscc...@gmail.com
Jesse,
Could you upstream or share your iperf porting? we also want to use this tool do some network testing.

Thanks
Xiang

--
You received this message because you are subscribed to the Google Groups "NuttX" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nuttx+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages