Showing posts with label C++. Show all posts
Showing posts with label C++. Show all posts

Shared libraries

Remember

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.

More details: Creating shared libraries
Very good How-To: Link

fscanf

Did not know this until yesterday.

fscanf (fptr, "%*s");
               ^^^
This reads the line from the file but does not store it in any local variable, as compared to this,

fscanf (fptr, "%s", buffer);

Handy '*' :)

Using goto is not evil.

In fact I find it a much better way of handling exceptions in C as compared to that fucked up if-else nesting that I did for that protocol stack!

Read this.

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);
}

Finding SLOC using wc

$ find . -name "*.cpp" -o -name "*.c" -o -name "*.h" | xargs wc -l 

Packing structures \ enums

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;

Signals

Linux Journal has couple of good articles on Signals on Linux.

Linux Signal Handling Model .. read
Linux Signals for the Application Programmer .. read

itoa() and scanf() alternative

itoa() is not defined in ANSI-C and is also not part of C++, but is supported by some compilers. It is however not advisable to use it in your code even if it is being supported by your compiler.

The better solution is to use sprintf().

Replace,

itoa (number, buffer, radix) with
sprintf (buffer, "%d", number);