The target where an application runs is remarkably similar to your desktop machine: it has a file system that is about the same and roughly the same set of device nodes. These similarities make it possible to use your desktop machine as a reasonable emulator for your target board. Yes, the processor is different; but between the kernel and the development language, the difference apparent to you is small to nonexistent, depending on the nature of the application. There are some key differences, however, which fall into two large categories: language and system related. Language-related differences appear as a result of the development language used to build the code; system-related differences have to do with the Linux kernel and root file system.
The target is slower than, has less memory than, has smaller fixed storage than, and probably doesn’t have the same input and output features as the desktop. However, the interface to those resources is identical to what’s on a desktop system. Because the interfaces are the same, the software can reasonably be run on both systems with similar results.
The Linux kernel provides a uniform interface to resources that stays the same even if the kernel is running on a different processor. Similarly, when programming in C, you use the same function calls for printing, reading input, interprocess communication, and process control. Compiling the C code with across-compiler outputs different object code, which, when run on the target, should work the same as the code run on the development host.
Coding for Portability
C isn’t absolutely uniform between a desktop system and an embedded target. Its creator referred to the language as a framework for creating assembler code; when you view it in that light, C leaves many differences exposed, not because of flaws in the language but because that’s how it was designed. Most users don’t encounter these problems unless they’re programming at a low level, but you should nonetheless understand them for the times they become an issue. For example, a system that transmits data over a TCP network must translate this data to big endian (endian is described in the next paragraph); if the target machine is big endian, this could be inadvertently skipped and the code would still run, but it would break on a little endian machine. There are, however, some factors that have to be taken into account almost every time we code portably in C, and on occasions, in other programming languages.
When you’re doing application development, the best strategy is to compile the code for execution on your development host and work out coding problems that aren’t architecture-specific before you test the code on the target. In order to do this, you must do some work to compile the code so it runs on the host and the target. Although the code won’t be running on the target right away, it’s a good habit to regularly compile it for the target so that any problems the compiler can spot can be fixed as you go instead of having to fix them all at once.
Higher-level languages don’t have these incompatibilities because they run on a virtual machine or interpreter (written in C) that hides these differences. The fact that C has these differences isn’t a flaw or feature but rather an artifact of the design philosophy of the language itself.
These relate primary to the differences in the target’s hardware and the software that serves as the interface. The primary way a userland program (that is, an application) interacts with the Linux kernel is through device nodes, which operate with the same set of rules as a file.
Device nodes can be anywhere on a system. The practice is to put them in the /dev directory. Writing data into the device node passes that data into the waiting device driver running in the kernel, which can then react to the input. Reading from a device node results in the device driver supplying data; the exact sort of data depends on the device driver.
Other device drivers supply an interface via system calls (also known as syscalls). Frequently, syscalls are supplied as well as a file interface. These are functions that register with the kernel to provide an interface that’s a function call. When you make a system call, the parameters passed into the function are passed to the kernel, which then passes them along to the device driver that registered the syscall. After the device driver’s call completes, any return data is passed back to you. Many device drivers that have a syscall type of interface supply an executable program that makes executing syscalls more convenient for you.
A syscall interface and a device-node interface are both acceptable ways to provide access to system resources. What matters as an application developer is what’s necessary to make those resources available on the development host. Many times, the development host can be populated with the same device drivers as the target machine. If that’s not possible, you can construct the application code with a wrapper around the bits of code that read from and write to the device driver or make syscalls. This extra bit of code introduces additional overhead and code size, but the amount is inconsequential.
It’s worth mentioning FIFOs, which are handy ways of emulating /dev/$(something) files that report the state of some hardware. As you recall from your data structures class, a FIFO is a First In First Out queue of data. In real life, it resembles a line at the bank: the order which the data is entered is the order in which it comes out the other side of the queue.In Linux, a FIFO is a special sort of internal data structure that has a file interface. Write to the FIFO, and it accumulates data so that when the reader asks for data, the queue is reduced. Create a FIFO by doing the following (you don’t need root access to do this):
$ mkfifo ~/test-fifo
You open the file with a program called tail that prints out the contents of the file as soon as data becomes available. Call this terminal one:
$ tail -f ~/test-fifo
In another terminal window (terminal two), you can write to this file by doing the following:
$ echo something > $/test-fifo
On terminal one, “something” appears. You can pass as much data as desired; for example:
$ ls / > $/test-fifo
The FIFO has a limited amount of resources to store the data after it’s been written but before it’s read. The current limit is one page size, or about 4KB.
The wonderful thought about FIFO is how it lets you read from it from the command line. This makes creating a simple fake device easy. A real-life example of this feature’s usefulness is a board with a device driver for some digital IO buttons and a potentiometer. The buttons have a device driver that updates a file /dev/buttons with a new line of data when the button changes state. The device has six buttons, and the contents of /dev/buttons when none have been clicked is
0 0 0 0 0 0 <newline>
The corresponding 0 changes to a 1 while you hold down the button:
0 1 0 0 0 0 <newline>
It changes back to a 0 when you release the button. The code that reads from this device driver does so in a loop with scanf(). To test the code on a desktop machine, I created a FIFO /dev/buttons and ran a script that wrote into the FIFO to simulate the buttons being clicked:
echo "0 0 1 0 0 0" > /dev/buttons That’s all the code necessary to emulate the device on a desktop. This interface also makes it much easier to test the code before deployment. When you’re thinking about how a device will interact with other parts of the system, put some thought into using what Linux already has in terms of interfaces, especially a file-type interface doing so lets you leverage a host of other features.
Linux Embedded systems Related Tutorials
Linux Embedded systems Related Interview Questions
|Linux Embedded systems Interview Questions||Red Hat Linux Essentials Interview Questions|
|Red Hat Linux System Administration Interview Questions||Ubuntu Certified Professional Interview Questions|
|IBM AIX Interview Questions||Solaris Interview Questions|
|HP-ux 11iv3 system administration Interview Questions||Red Hat cluster Interview Questions|
|Embedded C Interview Questions||Unix/Linux Interview Questions|
|Unix Shell Scripting Interview Questions||Solaris Administrator Interview Questions|
Linux Embedded systems Related Practice Tests
|Linux Embedded systems Practice Tests||Red Hat Linux Essentials Practice Tests|
|Red Hat Linux System Administration Practice Tests||Ubuntu Certified Professional Practice Tests|
|IBM AIX Practice Tests||Solaris Practice Tests|
|HP-ux 11iv3 system administration Practice Tests|
All rights reserved © 2020 Wisdom IT Services India Pvt. Ltd
Wisdomjobs.com is one of the best job search sites in India.