ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Let's say I wanted to create static binaries of my C code which were completely portable to any x86 system running a modern kernel. The idea being that it wouldn't even matter what version of libc is installed, because nothing is dynamically linked. For simplicity's sake, let's say that all the program does is perform calculations, read from stdin, and write to stdout, so the software environment is not a factor.
I know how to create static binaries, but a few relevant question come to mind:
1. I know that there are two major branches of kernel currently in use -- the lightweight 2.4 and the full-featured 2.6, plus of course minor revisions to each of these. Does the system call API vary between any of these versions, or is my executable runnable in all cases?
2. Assuming I was compiling with gcc, would I need to disable any default optimizations to achieve this goal? My binary should run on any x86 processor, so I wouldn't want some newer CPU instruction being used that would ruin this.
IA means a program written for i8086 can run on all IA-processors.
And now to the exceptions:
- not in PM if it uses segments or out, in, ... (special instructuns)
- not in V86M if hadware is accessed directly
- not in IA64M if it uses 8 bit registers
These exeptions realy only to assembler code. c,c++ has more difficult exeptions.
But the main thing is the OS. there are the most and individual exeptions.
the main is if you don't want to relay on kenel versions, don't include kernel haeders !!!
The only thing you can use of an OS are its syscalls but no new ones.
Including libs doesn't work no mather if dynamic linked or static except that you include all relationschips of a library inline, static. And that means most of the times inluding the whole kernel source code and that means it can not be run on a dynamic linked system.
And think about that kernel 2.6 can only be run on an i80686 or higher and kernel 2.4 I guess needs at minimum an i80386. So you can use i80386 32 bit instructions anytime.
And in assembler it is much easier to write undependent code for one architecture.
And in c, c++ it is easier to write code that can be run on different architectures, platforms.
Distribution: Ubuntu 11.4,DD-WRT micro plus ssh,lfs-6.6,Fedora 15,Fedora 16
Posts: 3,233
Rep:
indeed, if this were such the case than there wouldn't be the need for distribution specific packages (other than just the package format), however the only time a program can truly said to be 'portable' is as it's source code, which is why MOST GPL software includes a source release in addition to any binary releases if not some cases exclusively source releases, and even then source code because even if it was originally designed against one library set, it can easily be changed ('ported') by someone who knows what they are doing, to another similar set of libraries.
The distinction between the 2.4 and the 2.6 kernels is not as you suppose.
Every program is built for a certain environment and will operate correctly only if that environment exists. This can't be avoided.
That statement is obviously true, because it is a tautology. What I'm asking, though, is how do we create a binary that always works when we restrict the definition of "environment" to (1) having any Linux kernel from the 2.4 or 2.6 family, and (2) processed by any x86 compatible architecture.
If by "environment" you are referring to other issues like whether or not opengl graphics are available or whether or not we have cryptographic modules... those things are a concern in most practical programming. But we should be able to, at least for academic purposes, create binaries that will still execute regardless of the higher-level environment. For example: a program that simply performs a calculation and outputs the result to stdout.
bastl's response was helpful, though the question of default optimizations and instructions in gcc has not yet been directly addressed. (I.e., how portable is your gcc-compiled binary if you use default settings?)
... (I.e., how portable is your gcc-compiled binary if you use default settings?)
First of all, why default settings and not, say, '-march=i586' ?
...
Learn how live Linux/*BSD Cds/DVDs - they work on a whole bunch of computers without installation of the OS and utilities.
Last edited by Sergei Steshenko; 08-03-2011 at 12:48 AM.
let's say that all the program does is perform calculations, read from stdin, and write to stdout, so the software environment is not a factor
This is where you're wrong, or I am. While lowest common denominator assembler/code compiled to e.g. i586 can perform calculations in memory without caring about other 'high level' libraries, your communication with anything else at all is dependant on some shared standard. Notice that while basic operations are in an ISA, there's nothing about what defines 'stdin/stdout'. Either you need the specific environment's libraries, you assume they'll always be exactly the same at a binary level and break when they're not, or you require something directly reads from the memory you've manipulated without you being aware of it (except perhaps they change some specific location you're polling, but then what?).
This is where you're wrong, or I am. While lowest common denominator assembler/code compiled to e.g. i586 can perform calculations in memory without caring about other 'high level' libraries, your communication with anything else at all is dependant on some shared standard. Notice that while basic operations are in an ISA, there's nothing about what defines 'stdin/stdout'. Either you need the specific environment's libraries, you assume they'll always be exactly the same at a binary level and break when they're not, or you require something directly reads from the memory you've manipulated without you being aware of it (except perhaps they change some specific location you're polling, but then what?).
If we are talking about stdout/stdin/stderr, their existence is prescribed by "C" standard. No need to talk about machine code.
stdout/stdin/stderr IO is taken care of by standard "C" library. I.e. functions related to stdout/stdin/stderr IO must be present in every standards compliant platform.
Furthermore, *BSD is capable of running (many) Linux native binaries - *BSD has special Linux API emulation layer.
I think you're right, while binaries needn't come from C, the OP does restrict their 'completely portable to any x86 system' ideal to C code and Linux.
Isn't BSD technically an ABI level compatability, not API?
...
Isn't BSD technically an ABI level compatability, not API?
I am not sure. I think they have a special layer, i.e. they recognize that the ELF file to be executed is Linux, not *BSD, and call the layer. I think the mechanism is transparent to user, i.e. the user just invokes the program, the rest is taken care of automatically.
stdout/stdin/stderr IO is taken care of by standard "C" library. I.e. functions related to stdout/stdin/stderr IO must be present in every standards compliant platform.
Remember that the front end is standard, not the back end. The system calls open, read, write, etc. must be called the same on both machines, otherwise the standard C functions will do the wrong things. I honestly don't know if or how often system-call numbering changes*, but read, write, open, close, and stat are right up front on my system (/usr/include/asm/unistd_64.h).
The main reason there aren't portable binaries is the redundancy involved. We could all certainly fill our hard drives with only statically-linked binaries, but the majority of the binaries' sizes would be code that's consolidated in shared libraries on other systems. Of course, there are some things that won't work with static linking, and sometimes it changes licensing issues.
Kevin Barry
*After thinking about it a little, since you can generally upgrade from 2.4.* to 2.6.* or from one 2.6.* to another without recompiling your entire OS, system-call numbering probably doesn't change aside from adding new calls to the end.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.