There are various ways in which this can be done.
1. using #pragma pack()
#pragma pack(2)
typedef struct
{
char c;
int i;
} DataType;
#pragma pack()
This would pack the structure on a 2 byte boundary. If a tight packing is required use #pragma pack(1) instead. Compile it normally using gcc.
2. Using -fpack-struct
Instead of using the #pragma, we can directly use the compiler flags instead.
$gcc -Wall -fpack-struct -fshort-enums test.c -o test
This would pack all the structs to the 1 byte boundary and consider shorts for enums instead of integers
2. Using __attribute__ ((__packed__))
typedef struct
{
char c;
int i;
} __attribute__ ((__packed__))DataType;
.
Compile the code normally.
We can also do it this way
typedef struct
{
char c __attribute__ ((__packed__));
int i1 __attribute__ ((__packed__));
int i2;
} DataType;
Monday, March 7, 2011
your own system call in 5 easy steps
You *might* want to write your system call for various reasons
Assuming the path to your kernel source is "L". Create a new folder L/mysyscall. Inside the folder create the source file mysyscall.c and a Makefile
Step 1. Changing the System Table
L/arch/x86/kernel/syscall_table_32.S
Add your system call at the end of the file.
.long sys_new_system_call
Step 2. Changing the unistd.h
L/linux/include/asm-x86/unistd_32.h
Add your system call at the end of the existing list and append the next number
#define __NR_new_system_call XXX
Where XXX is the existing system call number plus 1. Also update the total system calls (as you just added another)
#define __NR_syscalls XXY
Where XXY is XXX+1
Step 3: Changing syscalls.h
L/include/linux/syscalls.h
Add the declaration of your system call at the end.
asmlinkage long new_system_call (whatever params you want to pass)
Step 4: Changing the kernel Makefile
Add the new folder to the kernel compile
core-y += /kernel /blah /blah /blah /mysyscall
Step 5: Write your system call
Write whatever crap you want to write inside the mysyscall.c file
asmlinkage long new_system_call (whatever params you want to pass)
{
// whatever you want to do
}
Change the makefile as well and add the following line
obj-y := mysyscall.o
Compile your kernel and test the system call from a user level program. You can create a header file that the user space program can use.
/* header.h */
#include < linux/unistd.h >
#define __NR_new_system_call XXX
/* if you system call returns int and takes no parameter
* use this macro
*/
_syscall0(int,new_system_call)
/* Otherwise, depending on the number of parameters
* being passed use the _syscallN macro, N being the no
* of params, like
_syscall1(int, new_system_call, int)
*/
Last thing to do is to test the code:
/* test client */
#include "header.h"
int main (void)
{
printf ("System call returned %d \n", new_system_call());
return 1;
}
NOTE
Starting around kernel 2.6.18, the _syscallXX macros were removed from header files supplied to user space. Instead we need to use syscall() function.
printf ("System call returned %d \n", syscall (__NR_new_system_call, params_if_any));
or, make the following changes in the header.h
/* header.h */
#include < linux/unistd.h >
#include < sys/syscall.h >
#define __NR_new_system_call XXX
long new_system_call (params_if_any)
{
return syscall (__NR_new_system_call, params_if_any);
}
Assuming the path to your kernel source is "L". Create a new folder L/mysyscall. Inside the folder create the source file mysyscall.c and a Makefile
Step 1. Changing the System Table
L/arch/x86/kernel/syscall_table_32.S
Add your system call at the end of the file.
.long sys_new_system_call
Step 2. Changing the unistd.h
L/linux/include/asm-x86/unistd_32.h
Add your system call at the end of the existing list and append the next number
#define __NR_new_system_call XXX
Where XXX is the existing system call number plus 1. Also update the total system calls (as you just added another)
#define __NR_syscalls XXY
Where XXY is XXX+1
Step 3: Changing syscalls.h
L/include/linux/syscalls.h
Add the declaration of your system call at the end.
asmlinkage long new_system_call (whatever params you want to pass)
Step 4: Changing the kernel Makefile
Add the new folder to the kernel compile
core-y += /kernel /blah /blah /blah /mysyscall
Step 5: Write your system call
Write whatever crap you want to write inside the mysyscall.c file
asmlinkage long new_system_call (whatever params you want to pass)
{
// whatever you want to do
}
Change the makefile as well and add the following line
obj-y := mysyscall.o
Compile your kernel and test the system call from a user level program. You can create a header file that the user space program can use.
/* header.h */
#include < linux/unistd.h >
#define __NR_new_system_call XXX
/* if you system call returns int and takes no parameter
* use this macro
*/
_syscall0(int,new_system_call)
/* Otherwise, depending on the number of parameters
* being passed use the _syscallN macro, N being the no
* of params, like
_syscall1(int, new_system_call, int)
*/
Last thing to do is to test the code:
/* test client */
#include "header.h"
int main (void)
{
printf ("System call returned %d \n", new_system_call());
return 1;
}
NOTE
Starting around kernel 2.6.18, the _syscallXX macros were removed from header files supplied to user space. Instead we need to use syscall() function.
printf ("System call returned %d \n", syscall (__NR_new_system_call, params_if_any));
or, make the following changes in the header.h
/* header.h */
#include < linux/unistd.h >
#include < sys/syscall.h >
#define __NR_new_system_call XXX
long new_system_call (params_if_any)
{
return syscall (__NR_new_system_call, params_if_any);
}
Shared libraries
gcc -shared -Wl,-soname,your_soname -o library_name file_list library_list
Which means, if you have a.c and b.c
gcc -fPIC -g -c -Wall a.c
gcc -fPIC -g -c -Wall b.c
gcc -shared -Wl,-soname,libmystuff.so.1 \
-o libmystuff.so.1.0.1 a.o b.o -lc
Then create the symbolic links to libmystuff.so and libmystuff.so.1 from libmystuff.so.1.0.1 and don't forget to add the libraries to the standard path /usr/local/lib OR add the path to LD_LIBRARY_PATH before executing.
Which means, if you have a.c and b.c
gcc -fPIC -g -c -Wall a.c
gcc -fPIC -g -c -Wall b.c
gcc -shared -Wl,-soname,libmystuff.so.1 \
-o libmystuff.so.1.0.1 a.o b.o -lc
Then create the symbolic links to libmystuff.so and libmystuff.so.1 from libmystuff.so.1.0.1 and don't forget to add the libraries to the standard path /usr/local/lib OR add the path to LD_LIBRARY_PATH before executing.
Thursday, March 3, 2011
POSIX Semaphores
Semaphores
POSIX 1003.1b semaphores provide an efficient form of interprocess communication. Cooperating processes can use semaphores to synchronize access to resources, most commonly, shared memory. Semaphores can also protect the following resources available to multiple processes from uncontrolled access:
* Global variables, such as file variables, pointers, counters, and data structures. Protecting these variables prevents simultaneous access by more than one process, such as reading information as it is being written by another process.
* Hardware resources, such as disk and tape drives. Hardware resources require controlled access because simultaneous access can result in corrupted data.
This chapter includes the following sections:
* Overview of Semaphores
* The Semaphore Interface
* Semaphore Example
Overview of Semaphores
Semaphores are used to control access to shared resources by processes. Counting semaphores have a positive integral value representing the number of processes that can concurrently lock the semaphore.
There are named and unnamed semaphores. Named semaphores provide access to a resource between multiple processes. Unnamed semaphores provide multiple accesses to a resource within a single process or between related processes. Some semaphore functions are specifically designed to perform operations on named or unnamed semaphores.
The semaphore lock operation checks to see if the resource is available or is locked by another process. If the semaphore’s value is a positive number, the lock is made, the semaphore value is decremented, and the process continues execution. If the semaphore’s value is zero or a negative number, the process requesting the lock waits (is blocked) until another process unlocks the resource. Several processes may be blocked waiting for a resource to become available.
The semaphore unlock operation increments the semaphore value to indicate that the resource is not locked. A waiting process, if there is one, is unblocked and it accesses the resource. Each semaphore keeps count of the number of processes waiting for access to the resource.
Semaphores are global entities and are not associated with any particular process. In this sense, semaphores have no owners making it impossible to track semaphore ownership for any purpose, for example, error recovery.
Semaphore protection works only if all the processes using the shared resource cooperate by waiting for the semaphore when it is unavailable and incrementing the semaphore value when relinquishing the resource. Since semaphores lack owners, there is no way to determine whether one of the cooperating processes has become uncooperative. Applications using semaphores must carefully detail cooperative tasks. All of the processes that share a resource must agree on which semaphore controls the resource.
POSIX 1003.1b semaphores are persistent. The value of the individual semaphore is preserved after the semaphore is no longer open. For example, a semaphore may have a value of 3 when the last process using the semaphore closes it. The next time a process opens that semaphore, it will find the semaphore has a value of 3. For this reason, cleanup operations are advised when using semaphores.
Note that because semaphores are persistent, you should call the sem_unlink function after a system reboot. After calling sem_unlink, you should call the sem_open function to establish new semaphores.
The semaphore descriptor is inherited across a fork. A parent process can create a semaphore, open it, and fork. The child process does not need to open the semaphore and can close the semaphore if the application is finished with it.
The Semaphore Interface
The following functions allow you to create and control P1003.1b semaphores:
Function Description
sem_close Deallocates the specified named semaphore
sem_destroy Destroys an unnamed semaphore
sem_getvalue Gets the value of a specified semaphore
sem_init Initializes an unnamed semaphore
sem_open Opens/creates a named semaphore for use by a process
sem_post Unlocks a locked semaphore
sem_trywait Performs a semaphore lock on a semaphore only if it can lock the semaphore without waiting for another process to unlock it
sem_unlink Removes a specified named semaphore
sem_wait Performs a semaphore lock on a semaphore
You create an unnamed semaphore with a call to the sem_init function, which initializes a counting semaphore with a specific value. To create a named semaphore, call sem_open with the O_CREAT flag specified. The sem_open function establishes a connection between the named semaphore and a process.
Semaphore locking and unlocking operations are accomplished with calls to the sem_wait, sem_trywait, and sem_post functions. You use these functions for named and unnamed semaphores. To retrieve the value of a counting semaphore, use the sem_getvalue function.
When the application is finished with an unnamed semaphore, the semaphore name is destroyed with a call to sem_destroy. To deallocate a named semaphore, call the sem_close function. The sem_unlink function removes a named semaphore. The semaphore is removed only when all processes using the semaphore have deallocated it using the sem_close function.
Creating and Opening a Semaphore
A call to the sem_init function creates an unnamed counting semaphore with a specific value. If you specify a non-zero value for the pshared argument, the semaphore can be shared between processes. If you specify the value zero, the semaphore can be shared among threads of the same process.
The sem_open function establishes a connection between a named semaphore and the calling process. Two flags control whether the semaphore is created or only accessed by the call. Set the O_CREAT flag to create a semaphore if it does not already exist. Set the O_EXCL flag along with the O_CREAT flag to indicate that the call to sem_open should fail if the semaphore already exists.
Subsequent to creating a semaphore with either sem_init or sem_open, the calling process can reference the semaphore by using the semaphore descriptor address returned from the call. The semaphore is available in subsequent calls to the sem_wait, sem_trywait, and sem_post functions, which control access to the shared resource. You can also retrieve the semaphore value by calls to sem_getvalue.
If your application consists of multiple processes that will use semaphores to synchronize access to a shared resource, each of these processes must first open the semaphore by a call to the sem_open function. After the initial call to the sem_init or sem_open function to establish the semaphore, each cooperating function must also call the sem_open function. If all cooperating processes are in the same working directory, just the name is sufficient. If the processes are contained in different working directories, the full pathname must be used. It is strongly recommended that the full pathname be used, such as /tmp/mysem1. The directory must exist for the call to succeed.
POSIX 1003.1b semaphores provide an efficient form of interprocess communication. Cooperating processes can use semaphores to synchronize access to resources, most commonly, shared memory. Semaphores can also protect the following resources available to multiple processes from uncontrolled access:
* Global variables, such as file variables, pointers, counters, and data structures. Protecting these variables prevents simultaneous access by more than one process, such as reading information as it is being written by another process.
* Hardware resources, such as disk and tape drives. Hardware resources require controlled access because simultaneous access can result in corrupted data.
This chapter includes the following sections:
* Overview of Semaphores
* The Semaphore Interface
* Semaphore Example
Overview of Semaphores
Semaphores are used to control access to shared resources by processes. Counting semaphores have a positive integral value representing the number of processes that can concurrently lock the semaphore.
There are named and unnamed semaphores. Named semaphores provide access to a resource between multiple processes. Unnamed semaphores provide multiple accesses to a resource within a single process or between related processes. Some semaphore functions are specifically designed to perform operations on named or unnamed semaphores.
The semaphore lock operation checks to see if the resource is available or is locked by another process. If the semaphore’s value is a positive number, the lock is made, the semaphore value is decremented, and the process continues execution. If the semaphore’s value is zero or a negative number, the process requesting the lock waits (is blocked) until another process unlocks the resource. Several processes may be blocked waiting for a resource to become available.
The semaphore unlock operation increments the semaphore value to indicate that the resource is not locked. A waiting process, if there is one, is unblocked and it accesses the resource. Each semaphore keeps count of the number of processes waiting for access to the resource.
Semaphores are global entities and are not associated with any particular process. In this sense, semaphores have no owners making it impossible to track semaphore ownership for any purpose, for example, error recovery.
Semaphore protection works only if all the processes using the shared resource cooperate by waiting for the semaphore when it is unavailable and incrementing the semaphore value when relinquishing the resource. Since semaphores lack owners, there is no way to determine whether one of the cooperating processes has become uncooperative. Applications using semaphores must carefully detail cooperative tasks. All of the processes that share a resource must agree on which semaphore controls the resource.
POSIX 1003.1b semaphores are persistent. The value of the individual semaphore is preserved after the semaphore is no longer open. For example, a semaphore may have a value of 3 when the last process using the semaphore closes it. The next time a process opens that semaphore, it will find the semaphore has a value of 3. For this reason, cleanup operations are advised when using semaphores.
Note that because semaphores are persistent, you should call the sem_unlink function after a system reboot. After calling sem_unlink, you should call the sem_open function to establish new semaphores.
The semaphore descriptor is inherited across a fork. A parent process can create a semaphore, open it, and fork. The child process does not need to open the semaphore and can close the semaphore if the application is finished with it.
The Semaphore Interface
The following functions allow you to create and control P1003.1b semaphores:
Function Description
sem_close Deallocates the specified named semaphore
sem_destroy Destroys an unnamed semaphore
sem_getvalue Gets the value of a specified semaphore
sem_init Initializes an unnamed semaphore
sem_open Opens/creates a named semaphore for use by a process
sem_post Unlocks a locked semaphore
sem_trywait Performs a semaphore lock on a semaphore only if it can lock the semaphore without waiting for another process to unlock it
sem_unlink Removes a specified named semaphore
sem_wait Performs a semaphore lock on a semaphore
You create an unnamed semaphore with a call to the sem_init function, which initializes a counting semaphore with a specific value. To create a named semaphore, call sem_open with the O_CREAT flag specified. The sem_open function establishes a connection between the named semaphore and a process.
Semaphore locking and unlocking operations are accomplished with calls to the sem_wait, sem_trywait, and sem_post functions. You use these functions for named and unnamed semaphores. To retrieve the value of a counting semaphore, use the sem_getvalue function.
When the application is finished with an unnamed semaphore, the semaphore name is destroyed with a call to sem_destroy. To deallocate a named semaphore, call the sem_close function. The sem_unlink function removes a named semaphore. The semaphore is removed only when all processes using the semaphore have deallocated it using the sem_close function.
Creating and Opening a Semaphore
A call to the sem_init function creates an unnamed counting semaphore with a specific value. If you specify a non-zero value for the pshared argument, the semaphore can be shared between processes. If you specify the value zero, the semaphore can be shared among threads of the same process.
The sem_open function establishes a connection between a named semaphore and the calling process. Two flags control whether the semaphore is created or only accessed by the call. Set the O_CREAT flag to create a semaphore if it does not already exist. Set the O_EXCL flag along with the O_CREAT flag to indicate that the call to sem_open should fail if the semaphore already exists.
Subsequent to creating a semaphore with either sem_init or sem_open, the calling process can reference the semaphore by using the semaphore descriptor address returned from the call. The semaphore is available in subsequent calls to the sem_wait, sem_trywait, and sem_post functions, which control access to the shared resource. You can also retrieve the semaphore value by calls to sem_getvalue.
If your application consists of multiple processes that will use semaphores to synchronize access to a shared resource, each of these processes must first open the semaphore by a call to the sem_open function. After the initial call to the sem_init or sem_open function to establish the semaphore, each cooperating function must also call the sem_open function. If all cooperating processes are in the same working directory, just the name is sufficient. If the processes are contained in different working directories, the full pathname must be used. It is strongly recommended that the full pathname be used, such as /tmp/mysem1. The directory must exist for the call to succeed.
API :
An API is a functional interface supplied by the operating system or a separately orderable licensed program that allows an application program written in a high-level language to use specific data or functions of the operating system or the licensed program.
Some APIs provide the same functions as control language (CL) commands and output file support. Some APIs provide functions that CL commands do not. Most APIs work more quickly and use less system overhead than the CL commands.
API use has the following advantages:
* APIs provide better performance when getting system information or when using system functions that are provided by CL commands or output file support.
* APIs provide system information and functions that are not available through CL commands.
* You can use calls from high-level languages to APIs.
* You can access system functions at a lower level than what was initially provided on the system.
* Data is often easier to work with when returned by an API.
Some APIs provide the same functions as control language (CL) commands and output file support. Some APIs provide functions that CL commands do not. Most APIs work more quickly and use less system overhead than the CL commands.
API use has the following advantages:
* APIs provide better performance when getting system information or when using system functions that are provided by CL commands or output file support.
* APIs provide system information and functions that are not available through CL commands.
* You can use calls from high-level languages to APIs.
* You can access system functions at a lower level than what was initially provided on the system.
* Data is often easier to work with when returned by an API.
Subscribe to:
Comments (Atom)