If parent doesn't use 'wait' system call for it's child, that child becomes zombie after end of execution.
(At zombie state, all allocated resources are removed, but it is still in process table for parent to get child's exit status.)
Here is very simple example

int
main (int argc, char* argv[]) {
    if (fork ()) { /* parent */
        [*A]
        sleep(999999);
    } else { /* child */
        sleep(1);
    }
    return 0;
}

In this case, child becomes zombie.
Simplest way to avoid making zombie is get exit status of child by use 'wait' system call at signal handler for SIGCHLD.
The point is, "DO NOT forget about getting child's exit status not to make zombie!"
At above example following codes should be added at [*A]

int status; wait(&status);

Done!

"LD_PRELOAD" is set to path of shared libraries. And those are loaded at first (even before C runtime).

LD_PRELOAD=./my.so:/path/to/a.so:/path/to/b.so

One good point is, "Developer can override symbols in the stock libraries, with symbols in LD_PRELOAD-specified-libraries.
For example, 'malloc' can be overridden with user-defined one by using LD_PRELOAD.

And another good tip is using LD_PRELOAD with '__attribute__((constructor))'.
'__attribute__((constructor))' is GCC specific syntax for C/C++.
Functions tagged '__attribute__((constructor))', are located at '.ctors' section of ELF and run when shared library is loaded.
('__attribute__((destuctor))' functions are located at '.dtors' section and run when shared library is unloaded.)
So, functions tagged '__attribute__((constructor))' in LD_PRELOAD-specified-library are executed before 'main' function.
It is fantastic, isn't it?

Real example is 'stdbuf' of gnu coreutils.
There are two main parts in 'stdbuf'. Here are details.

libstdbuf.so :
    libstdbuf.so has stdbuf() tagged '__attribute__((destructor))'.
    In stdbuf, modes of standard buffers - stdin, stdout, stderr - are modified.

stdbuf
    stdbuf puts 'libstdbuf.so' to LD_PRELOAD.
    And then, 'exec()' to main program to execute.

==> So, modes of standard buffer of main program can be changed

Enjoy trick of LD_PRELOAD!
For more detail example, see this post

There are lot's of articles that introduces way of using pipe and redirecting standard IO with those.
But, whenever try to do this, there is always big issue - buffer mode!
See following example.

< Tested on [Ubuntu EGLIBC 2.12.1-0ubuntu9] + [Ubuntu 2.6.35-23-generic-pae] >

#include <stdio.h>
#define _tstr "Sample Text\n"
int
main () {
    int fdp[2];
    pipe (fdp);
    if (0 != fork ()) {/* parent */
        dup2 (fdp[1],1); /* redirect standard out */
        /* fdp is not used anymore */
        close (fdp[0]);
        close (fdp[1]);
        [*A] /* <--- see below */
        sleep(99999999);
    } else {
        int  rb;
        char buf[100];
        dup2 (fdp[0],0); /* redirect standard in */
        /* fdp is not used anymore */
        close (fdp[0]);
        close (fdp[1]);
        if (0 >= (rb = [*B])) perror("IO Error\n"); /* <-- see below for [*B] */
        buf[rb] = 0; /* add trailing 0 */
        printf ("read from input:%s\n", buf);
        sleep(99999999);
    }
}

< *** [*A][*B] pair and result. *** >
OK pairs
    [*A] : write (fdp[1], ...)   |   [*B] : read (fdp[0], ...)
    [*A] : write (1, ...)        |   [*B] : read (fdp[0], ...)
    [*A] : write (1, ...)        |   [*B] : read (0, ...)
    [*A] : printf (_tstr); fflush (stdout) | [B] : read (1, ...)

NOT OK pairs - printed output is "read from input:" ('_tstr' is not printed immediately)
    [*A] : printf (_tstr);       | [*B] : read (0, ...)
        -> 'fflush' is missing here. But '\n' is at the end of test string...

Why 'printf' doesn't work without 'flush'?
'printf' uses standard buffer (at first IO operation, buffer is allocated by using 'malloc').
And because, output device is pipe - not console, buffered mode is used.
So, until flushing, all outputs are stored in buffer (NOT device).
To make pipe be REALLY like standard IO, mode of those buffer should be LINE BUFFERED mode.
So, 'setvbuf() or setlinebuf()' should be used at the first of [*A] as follows.

[*A] : setlinebuf (stdout); printf (_tstr);
    OR setvbuf (stdout, (char*)NULL, _IOLBF, 0); printf (_tstr);

It is simple, isn't it?

Here is more complicated cases.
See following example.

< Tested on [Ubuntu EGLIBC 2.12.1-0ubuntu9] + [Ubuntu 2.6.35-23-generic-pae] >

< main.c >
#include <stdio.h>
int
main() {
    int fdp[2]; /* pipe */
    pipe (fdp);
    if (0 != fork()) { /* parent */
        dup2 (fdp[1], 1); /* redirect standard out */
        close (fdp[0]);
        close (fdp[1]); 
        [*C] /* <-- see below */
        execlp ("test", (char*)0); /* run test (*1) */
    } else {
        int  rb;
        char buf[100];
        dup2 (fdp[0],0); /* redirect standard in */
        /* fdp is not used anymore */
        close (fdp[0]);
        close (fdp[1]);
        if (0 >= (rb = [*B])) perror("IO Error\n");
        buf[rb] = 0; /* add trailing 0 */
        printf ("read from input:%s\n", buf);
        sleep(99999999);
    }

< test.c > => test (executable)
int
main () {
    printf("This is Test!\n");
    sleep(99999999);
}

As above case, string from 'test' - "This is Test!" - is not printed to console immediately because it is buffered.
(Assume that, < test.c > SHOULD NOT be modified!)
Is there solution? Yes.
Before moving next step, see this post first.

Combination of LD_PRELOAD and  __attribute__ ((constructor)) is solution.
To do this, new file is added to make share library that will be preloaded.

< mystdbuf.c > => libmystdbuf.so
#include <stdio.h>
__attribute__ ((constructor)) static void
mystdbuf () {
    setvbuf (stdout, (char*)NULL, _IOLBF, 0);
}

And add following codes to section [*C]

putenv ("LD_PRELOAD=./libmystdbuf.so");

Resolved!

Another easy and popular solution is using 'stdbuf' command in gnu core-utils.
Replace (*1) with

execlp ("stdbuf", "stdbuf", "-oL", "./test", (char*)0);

As described in LINK above, mechanism of 'stdbuf' is exactly same with above manual solution!
Done!

* Following codes is to change byte[] to integer-typed-value and vice versa.
=> Note : JavaVM uses Big-Endian. And, size of each integer-type is byte(1), short(2), int(4), long(8).

public static final int
byteArrayToLongBE(byte[] b) {
    return ((b[0]&0xff) << 56) + ((b[1]&0xff) << 48)
         + ((b[2]&0xff) << 40) + ((b[3]&0xff) << 32)
         + ((b[4]&0xff) << 24) + ((b[5]&0xff) << 16)
         + ((b[6]&0xff) << 8)  + (b[7]&0xff);
}

public static final int
byteArrayToLongLE(byte[] b) {
    return (b[0]&0xff          + ((b[1]&0xff) << 8)
         + ((b[2]&0xff) << 16) + ((b[3]&0xff) << 24)
         + ((b[4]&0xff) << 32) + ((b[5]&0xff) << 40)
         + ((b[6]&0xff) << 48) + ((b[7]&0xff) << 56));
}

public static final int
byteArrayToIntBE(byte[] b) {
    return ((b[0]&0xff) << 24) + ((b[1]&0xff) << 16)
         + ((b[2]&0xff) << 8) + (b[3]&0xff);
}

public static final int
byteArrayToIntLE(byte[] b) {
    return (b[0]&0xff) + ((b[1]&0xff) << 8)
         + ((b[2]&0xff) << 16) + ((b[3]&0xff) << 24);
}

public static final short
byteArrayToShortBE(byte[] b) {
    return (short) (((b[0]&0xff) << 8) + (b[1]&0xff));
}

public static final short
byteArrayToShortLE(byte[] b) {
    return (short) ((b[0]&0xff) + ((b[1]&0xff) << 8));
}

public static final byte[]
longToByteArrayBE(long v) {
    return new byte[] {
            (byte)(v >>> 56), (byte)(v >>> 48),
            (byte)(v >>> 40), (byte)(v >>> 32),
            (byte)(v >>> 24), (byte)(v >>> 16),
            (byte)(v >>> 8),  (byte)v};
}

public static final byte[]
longToByteArrayLE(long v) {
    return new byte[] {
            (byte)v,          (byte)(v >>> 8),
            (byte)(v >>> 16), (byte)(v >>> 24),
            (byte)(v >>> 32), (byte)(v >>> 40),
            (byte)(v >>> 48), (byte)(v >>> 56)};
}

public static final byte[]
intToByteArrayBE(int v) {
    return new byte[] {
            (byte)(v >>> 24), (byte)(v >>> 16),
            (byte)(v >>> 8),  (byte)v};
}

public static final byte[]
intToByteArrayLE(int v) {
    return new byte[] {
            (byte)v,          (byte)(v >>> 8),
            (byte)(v >>> 16), (byte)(v >>> 24)};
}

public static final byte[]
shortToByteArrayBE(short v) {
    return new byte[] {(byte)(v >>> 8), (byte)v };
}

public static final byte[]
shortToByteArrayLE(short v) {
    return new byte[] {(byte)v, (byte)(v >>> 8) };
}

* Run process

// Recommanded
// Run shell command and return it's output as string
public static String
runCmd(String... cmd) {
    String r = "";
    try {
        // execute command
        ProcessBuilder pb = new ProcessBuilder(cmds);
        // pb.redirectErrorStream(true); // if needed.
        // wait till running is done.
        Process pr = pb.start();
        pr.waitFor() ;
        String line;
        // Reader output of sub process.
        BufferedReader br = new BufferedReader(new InputStreamReader(pr.getInputStream())) ;
        // Make output String object
        while ( null != (line = br.readLine()) ) r += line + "\n";
    } catch (Exception e) {
        ; // Exception Handling!
    }
    return r;
}

// OR
public static String
    runCmd(String[] cmds) {
    String r = "";
    try {
        // execute command
        Process pr = Runtime.getRuntime().exec(cmds) ;
        // wait till running is done.
        pr.waitFor() ;
        // Reader output of sub process.
        BufferedReader br = new BufferedReader(new InputStreamReader(pr.getInputStream())) ;
        // Make output String object
        String  line;
        while ( null != (line = br.readLine()) ) r += line + "\n";
    } catch (Exception e) {
        ; // Exception Handling!
    }
    return r;
}

* Run shell command

// We should invoke SHELL (not process command directly)
// See above for 'runCmd'
String cmd = "ls -al | grep text";
runCmd("/bin/bash", "-c", cmd);
// or : runCmd(new String[]{"/bin/bash", "-c", cmd});

* Multi-lined JLabel : We can do this by using HTML directly.

JLabel jl = new JLabel("<html>1st line<br>2nd line</html>");

* Loading java property

Properties prop = new Properties();
try {
    prop.load(new FileInputStream(property_file_path));
} catch (IOException e) {
    ; // exception handling
}

* String to Integer

try {
    int v = Integer.parseInt("3456");
} catch (NumberFormatException e) {
    ; // exception handling
}

=== to be continued...

'Language > Java' 카테고리의 다른 글

[Java][Test Code] ThreadPoolExecutor...  (0) 2013.09.25
[Java] Visibility에서 추가했으면 하는 것....  (0) 2011.04.21
[Java] Some notable stuffs of VM  (0) 2011.01.06
[Java] Package private in Java  (0) 2009.11.16
[Java][Tips] Compile...  (0) 2009.10.18

This is a kind of reminder.
(On Android)

Source code.

linux/input.h
    struct input_event;
: write 'struct input_event' to input event node.
ex.
    struct input_event ev;
    ...
    write(fd, &ev, sizeof(ev));
    ...

File system

/dev/input/*, /proc/bus/input/*

Touch event 
 

   type  code  value
<common> EV_ABS
EV_ABS
ABS_X
ABS_Y 
<value>
<value> 
Press (or Drag)Release EV_KEY
EV_KEY
BTN_TOUCH
BTN_TOUCH
1
0
<common>  EV_SYN 0 0

Key event

  type code value
Press EV_KEY <key code> 1
Release EV_KEY <key code> 0

Done. 

Sometimes, we want to access framebuffer directly.
Here is template and simple description to do this (on Android  as an example.)
(Note: This is just template. Some modification may be required according to driver.)
(Below way works on Android 2.3 ~ 4.1 emulator by turning off 'Use Host GPU' option at AVD Manager.)

Things used in this example.
(Refer kernel source code for details - comments in code.)
linux/fb.h
    - struct fb_var_screeninfo
        xres, yres, xres_virtual, yres_virtual, xoffset, yoffset, bits_per_pixel
    - struct fb_fix_screeninfo
        smem_len
    - FBIOGET_FSCREENINFO, FBIOGET_VSCREENINFO, FBIOPUT_VSCREENINFO
    - FB_ACTIVATE_NOW, FB_ACTIVATE_FORCE
See fbmem.c as your starting point of source analysis.

...
int                      fd;
struct fb_var_screeninfo vi;
struct fb_fix_screeninfo fi;
void*                    bits;
int                      bpp;    /* byte per pixel */
int                      stride; /* size of stride in pixel */

...
/* Open framebuffer */
if(0 > (fd = open("/dev/graphics/fb0", O_RDWR)) {
    printf("Fail to open fb\n");
    return -1;
}

/* Get fixed information */
if(0 > ioctl(fd, FBIOGET_FSCREENINFO, &fi)) {
    printf("Fail to get fixed info\n")
    return -1;
}

/* Get variable information */
if(0 > ioctl(fd, FBIOGET_VSCREENINFO, &vi)) {
    printf("Failed to get variable info\n");
    return -1;
}

/* Get raw bits buffer */
if(MAP_FAILED == (bits = mmap(0, fi.smem_len,
                              PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0))) {
    printf("Failed to mmap fb\n");
    return -1;
}

/* Calculate useful information */
bpp = vi.bits_per_pixel >> 3;
stride = fi.line_length / bpp;

...
/* Getting raw-image snapshot of current framebuffer */
void* curbits; /* current framebuffer raw data */
curbits = (unsigned char*)bits + (vi.xoffset + vi.yoffset*vi.xres_virtual)*bpp;
memcpy(raw_image_buffer, curbits, vi.yres*stride*bpp);

...
/* Modifying directly */
do_something(curbits...); /* change buffer directly... */

/* Refresh buffer manually */
vi.activate |= FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
if(0 > ioctl(fd, FBIOPUT_VSCREENINFO, &vi)) {
    printf("Failed to refresh\n");
    return -1;
}

Linux usually use 'double buffer'.
For this, usually,

vi.yres_virtual == vi.yres * 2
vi.yoffset == 0 or vi.yres
(0 for 1st buffer, vi.yres for 2nd buffer)

But, it's totally dependent on driver. So, to get portability, we should not assume those.

Following test is done with "Ubuntu EGLIBC 2.12.1-0ubuntu9"

Based on my simple test, 'select' function is poor to validate file descriptor.
In my test, select doesn't return error (-1) even for file descriptor 99999. Some times process is crashed - segment fault.
So, file descriptor should be validated before calling 'select'.
(I think I need to look into more about this. These are based on just test. So I'm not 100% sure about this.)

There is lot's of way. Here is well-known way.

is_valid_fd(int fd) { fcntl(fd, F_GETFL) != -1 || errno != EBADF; }

Summay. Be careful using 'select'!

'Language > C&C++' 카테고리의 다른 글

[C/C++][Linux] Tips about LD_PRELOAD  (0) 2010.12.13
[C/C++][linux] redirect standard io with pipe in code.  (0) 2010.12.10
[C/C++] Encapsulation tip in C.  (0) 2010.11.12
[C/C++] Tips and Memos  (0) 2010.11.12
[C/C++] Getting return address…  (0) 2010.11.03

Usually, pointer of not-opened-structure is used to hide module's information.
C dummies may use 'void*' to do this. But, it's not good way.
Let's see following example.
(Following codes are test in GCC4.4 with '-Wall' option.

typedef void module_t;             /* <-- *1 */
typedef struct _sModule module_t;  /* <-- *2 */

module_t* create_module(int arg);
int       do_something(module_t* m, int arg);
...
do_something((int*)m, 1); /* <-- *a */

Pointer of any type can be casted to 'void*', and 'void*' can be casted to pointer of any type without warning.
So, in case of (*1), (*a) doesn't generate any warning. That is, it is NOT TYPE SAFE (in compile time).
But, in case of (*2), GCC give warning like "... incompatible pointer type ...". It's TYPE SAFE.
And, interestingly, compiler doesn't complain anything about (*2) because, compiler doesn't need to know size of 'struct _sModule'.
Only pointer is used. So, knowing size of pointer type is enough and compiler already know it.
So, in terms of syntax, it's ok too!

Boolean to integer - C.

Let's think about the function that return 0 if false, otherwise 1.

 => Naive way : return (e)? 1: 0;

C doesn't support boolean type. Instead, 0 is false, non 0 is true in C.
There is no fixed value to represent TRUE.
But, as defined by 4.5/4, boolean true is promoted to 1, boolean false to 0.
So, we can improve this to

 => Better way : return !!(e);

And this way is also useful because we can get fixed integer value - integer 1 - for TRUE boolean value.

* The ORDER that function PARAMETERS are EVALUATED, is NOT SPECIFIED.
The only requirement is "Those should be fully evaluated before function is called."

alacarte의 한계를 넘어설 수 있다.
(이하는 Ubuntu 10.10에서의 내용이다.)

아래의 장소들과 깊은 관계되어 있다.
System default value가 들어 있는 곳 :

* /etc/xdg/ -> menus

User value가 들어 있는 곳

* ~/.config/ -> menus
 * ~/.local/share/ -> desktop-directories(- Directory), applications(- Menu Items)

.desktop 들어 있는 standard location

* /usr/share/applications/

크게 '.directory'와 '.desktop' 두 개의 확장자를 기억해 둘 필요가 있다.
'.directory'는 메뉴의 directory정보이고, '.desktop'은 메뉴 item의 정보라는 것 정도만 기억하자.

실험적으로, alacarte로 directory와 item을 만들어 보자.

pannel -> Application -> right click -> Edit Menus

로 들어가면 쉽게 만들어 볼 수 있다. GUI환경이라 skip...

만들었으면,  "~/.local/share/desktop-directories"로 가 보자. 그러면,  alacarte-madexx.directory 라는 file들이 새로 생겼을 것이고, 이 파일을 열어보면, GUI환경에서 새로 추가한 directory정보들과 일치함을 알 수 있다.
그리고 이번에는 "~/.local/share/applications"로 가 보자. alacarte-madexx.desktop 이라는 새로운 파일들을 볼 수 있고, 내용은 GUI환경에서 추가한, menu item정보임을 쉽게 알 수 있다.
이제 "~/.config/menus/"로 가서 applications.menu를 열어보자. 그러면, 위에서 봤던, '.directory' 파일과  '.desktop'파일의 이름이 나오는 메뉴 tag가 새로이 생성된 것을 알 수 있다.
간단히 정리하면, alacarte로 새로운 메뉴와 메뉴 item을 만들면 다음과 같은 파일이 생성/수정 된다.
(alacarte로 첫 메뉴/item을 만들었을 경우를 가정.)

* ~/.local/share/desktop-directories/alacarte-made.directory (추가) -- *1
* ~/.local/share/applications/alacarte-made.desktop (추가) -- *2
* ~/.config/menus/applications.menu (수정) -- *3

*1, *2는 메뉴/item 의 내용에 대한 정보이고, *3이 메뉴 구조에 대한 정보이다.

이제 case study로 실습해보자.
Ubuntu 10.10에서 Ubuntu Software Center에서 wine을 설치하고 이를 Applications 메인 메뉴에 등록해보자.
설치는 간단하니 skip하고...
설치가 끝나면 "/usr/share/applications"에  'wine.desktop, wine-xxxx.desktop' file들이 새롭게 생긴 것을 볼 수 있다. 이제 우리는 이걸 main menu에 잘 등록해 주기만 하면 된다.
그냥 하나씩 등록해도 되겠으나, 일반적으로 wine의 메뉴는 아래의 구조를 가진다.

wine
 +- Programs
 |    +- Accessories
 |        +- Notepad
 |
 |- Browse C: Drive
 |- Configure Wine
 +- Uninstall Wine Software

"각 '.desktop' 파일을 열어보면, category항목들이 보일 것이다. 특히 'wine-notepad.desktop'을 모면 "Categories=Wine-Programs-Accessories;"를 볼 수 있다.  즉 Category구조가 메뉴의 구조가 되고 있다. 이런 사항을 반영해서, *3 를 수정하면 된다.
그냥 direct로 수정해도 되겠으나, 차후 maintenance를 위해서 wine 메뉴는 따로 빼서 만들고 이를 *3에 merge하는 방식이 더 나아 보인다.
아래는 필자가 manual하게 추가한 결과이다.

*3에 추가

<Menu>
  <Name>Wine</Name>
  <MergeFile>wine.menu</MergeFile>
  <Directory>Wine.directory</Directory>
  <Include>
    <Category>Wine</Category>
    <Filename>wine.desktop</Filename>
  </Include>
  <Exclude>
    <Filename>wine.desktop</Filename>
  </Exclude>
  <AppDir>/home/hbg683/.local/share/applications</AppDir>
</Menu>

~/.config/menu/wine.menu 추가

<Menu>
  <Name>Wine</Name>
  <Directory>Wine.directory</Directory>
  <Include>
    <Category>Wine</Category>
     <Filename>wine.desktop</Filename>
  </Include>
  <AppDir>/home/hbg683/.local/share/applications</AppDir>
  <Menu>
    <Name>Programs</Name>
    <Directory>Wine-Program.directory</Directory>
    <DefaultLayout inline="false"/>
    <Menu>
      <Name>Accessories</Name>
      <Directory>Wine-Programs.Accessories.directory</Directory>
      <Include>
        <Category>Wine-Programs-Accessories</Category>
      </Include>
    </Menu>
    <DirectoryDir>/home/hbg683/.local/share/desktop-directories</DirectoryDir>
  </Menu>
  <DefaultLayout inline="false"/>
  <Exclude>
    <Filename>wine.desktop</Filename>
  </Exclude>
</Menu>

'~/.local/share/desktop-directories'에 각종 '.directory'파일 추가

Wine.directory
[Desktop Entry]
Name=Wine
Comment=Wine Windoes Program Loader
Type=Directory
Icon=wine
X-Ubuntu-Gettext-Domain=gnome-menus
Wine-Programs.directory, Wine-Programs-Accessories.directory 추가 (내용은 생략)

끝.

+ Recent posts