<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-462485765854905679</id><updated>2025-09-21T12:14:14.229+02:00</updated><category term="C"/><category term="UNIX"/><category term="Linux"/><category term="POSIX"/><category term="tty"/><category term="C++"/><category term="C99"/><category term="arithmetic-conversions"/><category term="clone"/><category term="cs-theory"/><category term="curses"/><category term="dmr"/><category term="fork"/><category term="glibc"/><category term="gnu-toolchain"/><category term="integer-promotions"/><category term="java"/><category term="ld"/><category term="linker"/><category term="non-MMU"/><category term="obituary"/><category term="propagation"/><category term="regex"/><category term="slang"/><category term="spring"/><category term="system-calls linux linux-kernel glibc syscalls"/><category term="termcap"/><category term="terminfo"/><category term="termios"/><category term="transactions"/><category term="vfork"/><category term="warnings"/><title type='text'>ninjalj&#39;s blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://ninjalj.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/462485765854905679/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://ninjalj.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>ninjalj</name><uri>http://www.blogger.com/profile/09820537051221341258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>11</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-462485765854905679.post-8357095739744293830</id><published>2018-04-03T14:09:00.000+02:00</published><updated>2018-04-03T14:09:29.033+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="system-calls linux linux-kernel glibc syscalls"/><title type='text'>How does a system call (e.g. fork()) work?</title><content type='html'>&lt;p&gt;(originally published at &lt;a href=&quot;https://stackoverflow.com/a/11570572/371250&quot;&gt;https://stackoverflow.com/a/11570572/371250&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;libc&lt;/strong&gt;&#39;s implementation of &lt;code&gt;fork()&lt;/code&gt; and other system calls contain special processor instructions that invoke a system call. System call invocation is architecture-specific, and can be a quite complex topic.&lt;/p&gt;

&lt;p&gt;Let&#39;s begin with a &quot;simple&quot; example, MIPS:&lt;/p&gt;

&lt;p&gt;On MIPS system calls are invoked via the SYSCALL instruction. So, libc&#39;s implementation of &lt;code&gt;fork()&lt;/code&gt; ends up putting some arguments on some registers, the system call number in regiter &lt;code&gt;v0&lt;/code&gt;, and issuing a &lt;code&gt;syscall&lt;/code&gt; instruction.&lt;/p&gt;

&lt;p&gt;On MIPS, this causes a &lt;code&gt;SYSCALL_EXCEPTION&lt;/code&gt; (exception number 8). When booting, the kernel associates exception 8 to a handling routine in &lt;code&gt;arch/mips/kernel/traps.c:trap_init()&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;set_except_vector(8, handle_sys);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So when the CPU receives an exception 8 because a program has issued a &lt;code&gt;syscall&lt;/code&gt; instruction, the CPU transitions into kernel mode, and begins executing the handler at &lt;code&gt;handle_sys&lt;/code&gt; at &lt;code&gt;/usr/src/linux/arch/mips/kernel/scall*.S&lt;/code&gt; (there are several files for the different 32/64 bits kernelspace/userspace combinations). That routine looks up the system call number in the system call table and jumps to the appropriate &lt;code&gt;sys_...()&lt;/code&gt; function, in this example &lt;code&gt;sys_fork()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now, x86 is more complicated. Traditionally, Linux used interrupt 0x80 to invoke system calls. This is associated to an x86 gate in &lt;code&gt;arch/x86/kernel/traps_*.c:trap_init()&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;set_system_gate(SYSCALL_VECTOR,&amp;amp;system_call);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;An x86 processor has several levels (rings) of privilege (since 80286). It is only possible to access (jump to) a lower ring (= more privilege) through predefined gates, which are special kinds of segment descriptors set by the kernel. So, when an &lt;code&gt;int 0x80&lt;/code&gt; is called, an interrupt is generated, the CPU looks up a special table called the IDT (Interrupt Descriptor Table), sees that it has a gate (a trap gate in x86, an interrupt gate in x86-64), and transitions into ring 0, beginning the execution of the &lt;code&gt;system_call&lt;/code&gt;/&lt;code&gt;ia32_syscall&lt;/code&gt; handler at &lt;code&gt;arch/x86/kernel/entry_32.S&lt;/code&gt;/&lt;code&gt;arch/x86/ia32/ia32entry.S&lt;/code&gt; (for x86/x86_64 respectively).&lt;/p&gt;

&lt;p&gt;But, since the Pentium Pro, there is an alternative way to invoke a system call: using the &lt;code&gt;SYSENTER&lt;/code&gt; instruction (AMD also has its own &lt;code&gt;SYSCALL&lt;/code&gt; instruction). This is a more efficient way to invoke a system call. The handler for this &quot;newer&quot; mechanism is set at &lt;code&gt;arch/x86/vdso/vdso32-setup.c:syscall32_cpu_init()&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#ifdef CONFIG_X86_64
[...]
void syscall32_cpu_init(void)
{
    if (use_sysenter &amp;lt; 0)
            use_sysenter = (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL);

    /* Load these always in case some future AMD CPU supports
       SYSENTER from compat mode too. */
    checking_wrmsrl(MSR_IA32_SYSENTER_CS, (u64)__KERNEL_CS);
    checking_wrmsrl(MSR_IA32_SYSENTER_ESP, 0ULL);
    checking_wrmsrl(MSR_IA32_SYSENTER_EIP, (u64)ia32_sysenter_target);

    wrmsrl(MSR_CSTAR, ia32_cstar_target);
}
[...]
#else
[...]
void enable_sep_cpu(void)
{
    int cpu = get_cpu();
    struct tss_struct *tss = &amp;amp;per_cpu(init_tss, cpu);

    if (!boot_cpu_has(X86_FEATURE_SEP)) {
            put_cpu();
            return;
    }

    tss-&amp;gt;x86_tss.ss1 = __KERNEL_CS;
    tss-&amp;gt;x86_tss.sp1 = sizeof(struct tss_struct) + (unsigned long) tss;
    wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
    wrmsr(MSR_IA32_SYSENTER_ESP, tss-&amp;gt;x86_tss.sp1, 0);
    wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long) ia32_sysenter_target, 0);
    put_cpu();
}
[...]
#endif  /* CONFIG_X86_64 */
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The above uses machine specific registers (MSRs) to do the setup. The handler routines are &lt;code&gt;ia32_sysenter_target&lt;/code&gt; and &lt;code&gt;ia32_cstar_target&lt;/code&gt; (this last one only for x86_64) (in &lt;code&gt;arch/x86/kernel/entry_32.S&lt;/code&gt; or &lt;code&gt;arch/x86/ia32/ia32entry.S&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choosing which syscall mechanism to use&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The linux kernel and glibc have a mechanism to choose between the different ways to invoke a system call.&lt;/p&gt;

&lt;p&gt;The kernel sets up a virtual shared library for each process, it&#39;s called the VDSO (virtual dynamic shared object), which you can see in the output of &lt;code&gt;cat /proc/&amp;lt;pid&amp;gt;/maps&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cat /proc/self/maps
08048000-0804c000 r-xp 00000000 03:04 1553592    /bin/cat
0804c000-0804d000 rw-p 00003000 03:04 1553592    /bin/cat
[...]
b7ee8000-b7ee9000 r-xp b7ee8000 00:00 0          [vdso]
[...]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This vdso, among other things, contains an appropriate system call invocation sequence for the CPU in use, e.g:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ffffe414 &amp;lt;__kernel_vsyscall&amp;gt;:
ffffe414:       51                      push   %ecx        ; \
ffffe415:       52                      push   %edx        ; &amp;gt; save registers
ffffe416:       55                      push   %ebp        ; /
ffffe417:       89 e5                   mov    %esp,%ebp   ; save stack pointer
ffffe419:       0f 34                   sysenter           ; invoke system call
ffffe41b:       90                      nop
ffffe41c:       90                      nop                ; the kernel will usually
ffffe41d:       90                      nop                ; return to the insn just
ffffe41e:       90                      nop                ; past the jmp, but if the
ffffe41f:       90                      nop                ; system call was interrupted
ffffe420:       90                      nop                ; and needs to be restarted
ffffe421:       90                      nop                ; it will return to this jmp
ffffe422:       eb f3                   jmp    ffffe417 &amp;lt;__kernel_vsyscall+0x3&amp;gt;
ffffe424:       5d                      pop    %ebp        ; \
ffffe425:       5a                      pop    %edx        ; &amp;gt; restore registers
ffffe426:       59                      pop    %ecx        ; /
ffffe427:       c3                      ret                ; return to caller
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In &lt;code&gt;arch/x86/vdso/vdso32/&lt;/code&gt; there are implementations using &lt;code&gt;int 0x80&lt;/code&gt;, &lt;code&gt;sysenter&lt;/code&gt; and &lt;code&gt;syscall&lt;/code&gt;, the kernel selects the appropriate one.&lt;/p&gt;

&lt;p&gt;To let userspace know that there is a vdso, and where it is located, the kernel sets &lt;code&gt;AT_SYSINFO&lt;/code&gt; and &lt;code&gt;AT_SYSINFO_EHDR&lt;/code&gt; entries in the auxiliary vector (&lt;code&gt;auxv&lt;/code&gt;, the 4th argument to &lt;code&gt;main()&lt;/code&gt;, after &lt;code&gt;argc, argv, envp&lt;/code&gt;, which is used to pass some information from the kernel to newly started processes). &lt;code&gt;AT_SYSINFO_EHDR&lt;/code&gt; points to the ELF header of the vdso, &lt;code&gt;AT_SYSINFO&lt;/code&gt; points to the vsyscall implementation:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ LD_SHOW_AUXV=1 id    # tell the dynamic linker ld.so to output auxv values
AT_SYSINFO:      0xb7fd4414
AT_SYSINFO_EHDR: 0xb7fd4000
[...]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;glibc uses this information to locate the &lt;code&gt;vsyscall&lt;/code&gt;. It stores it into the dynamic loader global &lt;code&gt;_dl_sysinfo&lt;/code&gt;, e.g.:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;glibc-2.16.0/elf/dl-support.c:_dl_aux_init():
ifdef NEED_DL_SYSINFO
  case AT_SYSINFO:
    GL(dl_sysinfo) = av-&amp;gt;a_un.a_val;
    break;
#endif
#if defined NEED_DL_SYSINFO || defined NEED_DL_SYSINFO_DSO
  case AT_SYSINFO_EHDR:
    GL(dl_sysinfo_dso) = (void *) av-&amp;gt;a_un.a_val;
    break;
#endif

glibc-2.16.0/elf/dl-sysdep.c:_dl_sysdep_start()

glibc-2.16.0/elf/rtld.c:dl_main:
GLRO(dl_sysinfo) = GLRO(dl_sysinfo_dso)-&amp;gt;e_entry + l-&amp;gt;l_addr;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and in a field in the header of the TCB (thread control block):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;glibc-2.16.0/nptl/sysdeps/i386/tls.h

_head-&amp;gt;sysinfo = GLRO(dl_sysinfo)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If the kernel is old and doesn&#39;t provide a vdso, glibc provides a default implementation for &lt;code&gt;_dl_sysinfo&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;.hidden _dl_sysinfo_int80:
int $0x80
ret
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When a program is compiled against glibc, depending on circumstances, a choice is made between different ways of invoking a system call:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;glibc-2.16.0/sysdeps/unix/sysv/linux/i386/sysdep.h:
/* The original calling convention for system calls on Linux/i386 is
   to use int $0x80.  */
#ifdef I386_USE_SYSENTER
# ifdef SHARED
#  define ENTER_KERNEL call *%gs:SYSINFO_OFFSET
# else
#  define ENTER_KERNEL call *_dl_sysinfo
# endif
#else
# define ENTER_KERNEL int $0x80
#endif
&lt;/code&gt;&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;int 0x80&lt;/code&gt; ← the traditional way&lt;/li&gt;
&lt;li&gt;&lt;code&gt;call *%gs:offsetof(tcb_head_t, sysinfo)&lt;/code&gt; ← &lt;code&gt;%gs&lt;/code&gt; points to the TCB, so this jumps indirectly through the pointer to vsyscall stored in the TCB. This is prefered for objects compiled as PIC.
   This requires TLS initialization. For dynamic executables, TLS is initialized by ld.so. For static PIE executables, TLS is initialized by
   __libc_setup_tls().
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;call *_dl_sysinfo&lt;/code&gt; ← this jumps indirectly through the global variable. This requires relocation of _dl_sysinfo, so it is avoided for objects compiled as PIC.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, in x86:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;                       fork()
                         ↓
int 0x80 / call *%gs:0x10 / call *_dl_sysinfo 
  |                ↓              ↓
  |       (in vdso) int 0x80 / sysenter / syscall
  ↓                ↓              ↓            ↓
      system_call     | ia32_sysenter_target | ia32_cstar_target
                          ↓
                       sys_fork()
&lt;/code&gt;&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://ninjalj.blogspot.com/feeds/8357095739744293830/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ninjalj.blogspot.com/2018/04/how-does-system-call-eg-fork-work.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/462485765854905679/posts/default/8357095739744293830'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/462485765854905679/posts/default/8357095739744293830'/><link rel='alternate' type='text/html' href='http://ninjalj.blogspot.com/2018/04/how-does-system-call-eg-fork-work.html' title='How does a system call (e.g. fork()) work?'/><author><name>ninjalj</name><uri>http://www.blogger.com/profile/09820537051221341258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-462485765854905679.post-5377081945893247041</id><published>2013-03-12T00:43:00.000+01:00</published><updated>2013-03-12T00:43:41.475+01:00</updated><title type='text'></title><content type='html'>&lt;p&gt;In a &lt;a href=&quot;http://programmers.stackexchange.com/a/190101&quot;&gt;comment&lt;/a&gt; in programmers.SE, &lt;a href=&quot;http://programmers.stackexchange.com/users/24392/dibbeke&quot;&gt;Dibbeke&lt;/a&gt; states the following:&lt;/p&gt;
&lt;p&gt;&lt;blockquote&gt;Small hint here: your most important liability in programming is your code.
So, less is truly more here.&lt;/blockquote&gt;&lt;/p&gt;
&lt;p&gt;Many people view code as an asset. It is not. Code is a liability. The
functionality code provides is the asset. So, it follows that you should try to
get that functionality with the minimum amount of code. Sometimes, you should
even forgo some functionality, because its cost in code (and the cost of code
is _not_ the cost of writing it) exceeds the value it provides.&lt;/p&gt;
&lt;p&gt;See also: &lt;a href=&quot;http://c2.com/cgi/wiki?SoftwareAsLiability&quot;&gt;SoftwareAsLiability&lt;/a&gt; and &lt;a href=&quot;http://c2.com/cgi/wiki?LegacyCode&quot;&gt;LegacyCode&lt;/a&gt; at the &lt;a href=&quot;http://c2.com/cgi/wiki?WelcomeVisitors&quot;&gt;c2.com wiki&lt;/a&gt;.</content><link rel='replies' type='application/atom+xml' href='http://ninjalj.blogspot.com/feeds/5377081945893247041/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ninjalj.blogspot.com/2013/03/in-comment-in-programmers.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/462485765854905679/posts/default/5377081945893247041'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/462485765854905679/posts/default/5377081945893247041'/><link rel='alternate' type='text/html' href='http://ninjalj.blogspot.com/2013/03/in-comment-in-programmers.html' title=''/><author><name>ninjalj</name><uri>http://www.blogger.com/profile/09820537051221341258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-462485765854905679.post-991799691033775762</id><published>2011-11-17T01:26:00.001+01:00</published><updated>2011-12-03T02:20:27.907+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C"/><category scheme="http://www.blogger.com/atom/ns#" term="glibc"/><category scheme="http://www.blogger.com/atom/ns#" term="gnu-toolchain"/><category scheme="http://www.blogger.com/atom/ns#" term="ld"/><category scheme="http://www.blogger.com/atom/ns#" term="linker"/><category scheme="http://www.blogger.com/atom/ns#" term="Linux"/><category scheme="http://www.blogger.com/atom/ns#" term="warnings"/><title type='text'>Your own linker warnings using the GNU toolchain</title><content type='html'>&lt;style type=&quot;text/css&quot;&gt;
  p {text-align: justify;}
  pre { color: #000000; background-color: #ffffff; }
  .code { color: #000000; background-color: #ffffff; }
  div.code { border: 1px dashed; margin: 5px; padding: 0px 5px;}
  .Constant { color: #c00058; }
  .PreProc { color: Magenta; }
  .Special { color: SlateBlue; }
  .Statement { color: Brown; }
  .Type { color: SeaGreen; }
&lt;/style&gt;&lt;br /&gt;
&lt;p&gt;You&#39;ve probably seen linker warnings like these:&lt;/p&gt;&lt;code&gt;&lt;pre&gt;linkwarnmain.c:(.text+0x1d): warning: foo is deprecated, please use the shiny new foobar function
linkwarnmain.c:(.text+0x27): warning: the use of `tmpnam&#39; is dangerous, better use `mkstemp&#39;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;
&lt;p&gt;These warnings are actually stored in ELF sections named &lt;code&gt;.gnu.warning.&lt;i&gt;symbolname&lt;/i&gt;&lt;/code&gt;:&lt;/p&gt;&lt;code&gt;&lt;pre&gt;$ objdump -s -j .gnu.warning.gets /lib/libc.so.6

/lib/libc.so.6:     file format elf32-i386

Contents of section .gnu.warning.gets:
 0000 74686520 60676574 73272066 756e6374  the `gets&#39; funct
 0010 696f6e20 69732064 616e6765 726f7573  ion is dangerous
 0020 20616e64 2073686f 756c6420 6e6f7420   and should not
 0030 62652075 7365642e 00                 be used..&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;
&lt;p&gt;So when you try to use a symbol, if the linker sees a section whose name matches the above pattern, it emits the corresponding warning message.&lt;/p&gt;&lt;p&gt;You can add your own linker warnings to your source files:&lt;/p&gt;&lt;code&gt;linkwarn.c&lt;/code&gt;&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;Type&quot;&gt;void&lt;/span&gt; foo(&lt;span class=&quot;Type&quot;&gt;void&lt;/span&gt;)
{
}

&lt;span class=&quot;Type&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;Type&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;Type&quot;&gt;char&lt;/span&gt; foo_warning[] __attribute__((section(&lt;span class=&quot;Constant&quot;&gt;&amp;quot;.gnu.warning.foo&amp;quot;&lt;/span&gt;))) =
        &lt;span class=&quot;Constant&quot;&gt;&amp;quot;foo is deprecated, please use the shiny new foobar function&amp;quot;&lt;/span&gt;;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
&lt;code&gt;linkwarnmain.c&lt;/code&gt;&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;Type&quot;&gt;void&lt;/span&gt; foo(&lt;span class=&quot;Type&quot;&gt;void&lt;/span&gt;);

&lt;span class=&quot;Type&quot;&gt;int&lt;/span&gt; main()
{
        foo();

        &lt;span class=&quot;Statement&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;0&lt;/span&gt;;
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
&lt;p&gt;Then, when you compile, you will get a warning:&lt;/p&gt;&lt;code&gt;&lt;pre&gt;$ gcc -Wall -c linkwarn.c
$ gcc -Wall -o linkwarnmain linkwarnmain.c linkwarn.o
/tmp/ccyHLTw6.o: In function `main&#39;:
linkwarnmain.c:(.text+0x1d): warning: foo is deprecated, please use the shiny new foobar function
&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;
&lt;p&gt;&lt;i&gt;glibc&lt;/i&gt; machinery for emitting linker warnings is a little bit more complicated:&lt;/p&gt;&lt;code&gt;libc-symbols.h&lt;/code&gt;&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;&lt;pre&gt;...
&lt;span class=&quot;PreProc&quot;&gt;#ifdef HAVE_ELF&lt;/span&gt;

&lt;span class=&quot;Comment&quot;&gt;/*&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt; We want the .gnu.warning.SYMBOL section to be unallocated.  &lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;*/&lt;/span&gt;
&lt;span class=&quot;PreProc&quot;&gt;# ifdef HAVE_ASM_PREVIOUS_DIRECTIVE&lt;/span&gt;
&lt;span class=&quot;PreProc&quot;&gt;#  define __make_section_unallocated(section_string)    \&lt;/span&gt;
&lt;span class=&quot;PreProc&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;Statement&quot;&gt;asm&lt;/span&gt;&lt;span class=&quot;PreProc&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;Constant&quot;&gt;&amp;quot;.section &amp;quot;&lt;/span&gt;&lt;span class=&quot;PreProc&quot;&gt; section_string &lt;/span&gt;&lt;span class=&quot;Constant&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;Special&quot;&gt;\n\t&lt;/span&gt;&lt;span class=&quot;Constant&quot;&gt;.previous&amp;quot;&lt;/span&gt;&lt;span class=&quot;PreProc&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;PreProc&quot;&gt;# elif defined HAVE_ASM_POPSECTION_DIRECTIVE&lt;/span&gt;
&lt;span class=&quot;PreProc&quot;&gt;#  define __make_section_unallocated(section_string)    \&lt;/span&gt;
&lt;span class=&quot;PreProc&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;Statement&quot;&gt;asm&lt;/span&gt;&lt;span class=&quot;PreProc&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;Constant&quot;&gt;&amp;quot;.pushsection &amp;quot;&lt;/span&gt;&lt;span class=&quot;PreProc&quot;&gt; section_string &lt;/span&gt;&lt;span class=&quot;Constant&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;Special&quot;&gt;\n\t&lt;/span&gt;&lt;span class=&quot;Constant&quot;&gt;.popsection&amp;quot;&lt;/span&gt;&lt;span class=&quot;PreProc&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;PreProc&quot;&gt;# else&lt;/span&gt;
&lt;span class=&quot;PreProc&quot;&gt;#  define __make_section_unallocated(section_string)&lt;/span&gt;
&lt;span class=&quot;PreProc&quot;&gt;# endif&lt;/span&gt;

&lt;span class=&quot;Comment&quot;&gt;/*&lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt; Tacking on &amp;quot;\n\t#&amp;quot; to the section name makes gcc put it&#39;s bogus&lt;/span&gt;
&lt;span class=&quot;Comment&quot;&gt;   section attributes on what looks like a comment to the assembler.  &lt;/span&gt;&lt;span class=&quot;Comment&quot;&gt;*/&lt;/span&gt;
&lt;span class=&quot;PreProc&quot;&gt;# ifdef HAVE_SECTION_QUOTES&lt;/span&gt;
&lt;span class=&quot;PreProc&quot;&gt;#  define __sec_comment &lt;/span&gt;&lt;span class=&quot;Constant&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;Special&quot;&gt;\&amp;quot;\n\t&lt;/span&gt;&lt;span class=&quot;Constant&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;Special&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span class=&quot;Constant&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;PreProc&quot;&gt;# else&lt;/span&gt;
&lt;span class=&quot;PreProc&quot;&gt;#  define __sec_comment &lt;/span&gt;&lt;span class=&quot;Constant&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;Special&quot;&gt;\n\t&lt;/span&gt;&lt;span class=&quot;Constant&quot;&gt;#&amp;quot;&lt;/span&gt;
&lt;span class=&quot;PreProc&quot;&gt;# endif&lt;/span&gt;
&lt;span class=&quot;PreProc&quot;&gt;# define link_warning(symbol, msg) \&lt;/span&gt;
&lt;span class=&quot;PreProc&quot;&gt;  __make_section_unallocated (&lt;/span&gt;&lt;span class=&quot;Constant&quot;&gt;&amp;quot;.gnu.warning.&amp;quot;&lt;/span&gt;&lt;span class=&quot;PreProc&quot;&gt; #symbol) \&lt;/span&gt;
&lt;span class=&quot;PreProc&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;Type&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;PreProc&quot;&gt; &lt;/span&gt;&lt;span class=&quot;Type&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;PreProc&quot;&gt; &lt;/span&gt;&lt;span class=&quot;Type&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;PreProc&quot;&gt; __evoke_link_warning_##symbol[]     \&lt;/span&gt;
&lt;span class=&quot;PreProc&quot;&gt;    __attribute__ ((used, section (&lt;/span&gt;&lt;span class=&quot;Constant&quot;&gt;&amp;quot;.gnu.warning.&amp;quot;&lt;/span&gt;&lt;span class=&quot;PreProc&quot;&gt; #symbol __sec_comment))) \&lt;/span&gt;
&lt;span class=&quot;PreProc&quot;&gt;    = msg;&lt;/span&gt;
...
&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The warning message is marked as &lt;code&gt;used&lt;/code&gt; so the optimizer doesn&#39;t decide to completely optimize it out of existence. Also, the section is not marked as allocatable to prevent the loader from loading it into memory. Since gcc&#39;s section attribute doesn&#39;t allow to change its default flags, the solution is to declare the section using asm, return to the previous section (the one the compiler was using beforehand), and prevent (via &lt;code&gt;__sec_comment&lt;/code&gt;) the assembler from seeing the flags that gcc adds in its section attribute output. Otherwise we&#39;d have something similar to:&lt;/p&gt;&lt;code&gt;&lt;pre&gt;$ gcc -Wall -S linkwarn.c
$ cat linkwarn.s
        .file   &quot;linkwarn.c&quot;
        .text
.globl foo
        .type   foo, @function
foo:
        pushl   %ebp
        movl    %esp, %ebp
        popl    %ebp
        ret
        .size   foo, .-foo
        .section        .gnu.warning.foo,&quot;a&quot;,@progbits
        .align 32
        .type   foo_warning, @object
        .size   foo_warning, 60
foo_warning:
        .string &quot;foo is deprecated, please use the shiny new foobar function&quot;
        .section        .note.GNU-stack,&quot;&quot;,@progbits
        .ident  &quot;GCC: (GNU) 3.4.5 (Gentoo 3.4.5-r1, ssp-3.4.5-1.0, pie-8.7.9)&quot;
&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;p&gt;... where the section is marked as allocatable via the &quot;a&quot; flag.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://ninjalj.blogspot.com/feeds/991799691033775762/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ninjalj.blogspot.com/2011/11/your-own-linker-warnings-using-gnu.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/462485765854905679/posts/default/991799691033775762'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/462485765854905679/posts/default/991799691033775762'/><link rel='alternate' type='text/html' href='http://ninjalj.blogspot.com/2011/11/your-own-linker-warnings-using-gnu.html' title='Your own linker warnings using the GNU toolchain'/><author><name>ninjalj</name><uri>http://www.blogger.com/profile/09820537051221341258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-462485765854905679.post-7453852099486313048</id><published>2011-10-18T00:13:00.001+02:00</published><updated>2011-12-03T02:21:19.187+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="curses"/><category scheme="http://www.blogger.com/atom/ns#" term="slang"/><category scheme="http://www.blogger.com/atom/ns#" term="termcap"/><category scheme="http://www.blogger.com/atom/ns#" term="terminfo"/><category scheme="http://www.blogger.com/atom/ns#" term="tty"/><category scheme="http://www.blogger.com/atom/ns#" term="UNIX"/><title type='text'>Terminals in *nix</title><content type='html'>&lt;style type=&quot;text/css&quot;&gt;p {text-align: justify}&lt;/style&gt;&lt;br /&gt;
&lt;p&gt;Terminals were hardware devices that consisted of a keyboard and an output device (initially a line printer, later a CRT monitor). A large computer could have several remote terminals connected to it. Each terminal would have a protocol for communicating efficiently with the computer, for CRT-based terminals this includes having special &quot;&lt;em&gt;control sequences&lt;/em&gt;&quot; to change cursor position, erase parts of the current line/screen, switch to an alternate full-screen mode, ...&lt;/p&gt;&lt;p&gt;A terminal emulator is an application emulating one of those older terminals. It allows to do functions like cursor positioning, setting foreground and background colors, ... Terminal emulators try to emulate some specific terminal protocol, but each has its own set of quirks and deviations.&lt;/p&gt;&lt;p&gt;Unix systems have databases describing terminals and terminal emulators, so applications are abstracted away from the particular terminal (or terminal emulator) in use. An older database is &lt;a href=&quot;http://man7.org/linux/man-pages/online/pages/man5/termcap.5.html&quot;&gt;&lt;code&gt;termcap(5)&lt;/code&gt;&lt;/a&gt;, while &lt;code&gt;terminfo(5)&lt;/code&gt; is a newer database. These databases allow applications to query for the capabilities of the terminal in use. Capabilities can be booleans, numeric capabilities, or even string capabilities, e.g.: if a specific terminal type has/supports a &lt;strong&gt;F12&lt;/strong&gt; key, it will have a capability &quot;&lt;em&gt;key_f12&lt;/em&gt;&quot; (long terminfo name), &quot;&lt;em&gt;kf12&lt;/em&gt;&quot; (short terminfo name), &quot;&lt;em&gt;F2&lt;/em&gt;&quot; (termcap name) describing the string that key produces. Try it with: &lt;code&gt;tput kf12 | od -tx1&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Since programming directly with capabilities can be cumbersome, applications typically use a higher-level library like curses/ncurses, slang, etc...&lt;/p&gt;&lt;p&gt;There is a special environment variable called &lt;code&gt;TERM&lt;/code&gt; that tells applications what terminal type they are talking to. This variable should be set to the exact terminal type if it exists in the database, for best results. This just tells the application which precise protocol and protocol deviations does the terminal understand. Changing the &lt;code&gt;TERM&lt;/code&gt; variable does not change the terminal type, it just changes the terminal type the application thinks it is talking to.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://ninjalj.blogspot.com/feeds/7453852099486313048/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ninjalj.blogspot.com/2011/10/terminals-in-nix.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/462485765854905679/posts/default/7453852099486313048'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/462485765854905679/posts/default/7453852099486313048'/><link rel='alternate' type='text/html' href='http://ninjalj.blogspot.com/2011/10/terminals-in-nix.html' title='Terminals in *nix'/><author><name>ninjalj</name><uri>http://www.blogger.com/profile/09820537051221341258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-462485765854905679.post-8639694139828251156</id><published>2011-10-17T23:58:00.001+02:00</published><updated>2011-12-03T02:21:55.957+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C"/><category scheme="http://www.blogger.com/atom/ns#" term="dmr"/><category scheme="http://www.blogger.com/atom/ns#" term="obituary"/><category scheme="http://www.blogger.com/atom/ns#" term="UNIX"/><title type='text'>dmr</title><content type='html'>&lt;style type=&quot;text/css&quot;&gt;p {text-align: justify}&lt;/style&gt;&lt;br /&gt;
&lt;p&gt;I remember SuSE Linux had a motd that simply said: &quot;Have fun...&quot; That has always been the spirit of Unix, having an environment in which it is fun to work and tinker about. We owe that to Ken Thompson, Dennis Ritchie and their colleagues at Bell Labs (&lt;a href=&quot;http://www.princeton.edu/~hos/Mahoney/unixpeople.htm&quot;&gt;http://www.princeton.edu/~hos/Mahoney/unixpeople.htm&lt;/a&gt;).&lt;/p&gt;&lt;p&gt;Dennis Ritchie also evolved Thompson&#39;s B into C, giving us a concise and practical systems programming language. Kernighan and Ritchie taught many people how to write great code, some of those people taught other people, directly, or simply by sharing great code. The end result has been a ripple effect that has had a profound and positive impact on how many of us code. Not many people in history have influenced the work of others so much.&lt;/p&gt;&lt;p&gt;Dennis Ritchie is no longer with us, he will be greatly missed. He is among those luminaries we will never forget. The computing community will never forget Jon Postel, Richard Stevens and Dennis Ritchie.&lt;/p&gt;Obituaries:&lt;br /&gt;
&lt;a href=&quot;http://www.nytimes.com/2011/10/14/technology/dennis-ritchie-programming-trailblazer-dies-at-70.html?hp&quot;&gt;http://www.nytimes.com/2011/10/14/technology/dennis-ritchie-programming-trailblazer-dies-at-70.html?hp&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://www.guardian.co.uk/technology/2011/oct/13/dennis-ritchie&quot;&gt;http://www.guardian.co.uk/technology/2011/oct/13/dennis-ritchie&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://www.bbc.co.uk/news/technology-15287391&quot;&gt;http://www.bbc.co.uk/news/technology-15287391&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://ninjalj.blogspot.com/feeds/8639694139828251156/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ninjalj.blogspot.com/2011/10/dmr.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/462485765854905679/posts/default/8639694139828251156'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/462485765854905679/posts/default/8639694139828251156'/><link rel='alternate' type='text/html' href='http://ninjalj.blogspot.com/2011/10/dmr.html' title='dmr'/><author><name>ninjalj</name><uri>http://www.blogger.com/profile/09820537051221341258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-462485765854905679.post-4778384965436099465</id><published>2011-10-10T21:41:00.001+02:00</published><updated>2011-12-03T02:22:25.258+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C"/><category scheme="http://www.blogger.com/atom/ns#" term="C++"/><title type='text'>Tentative Definitions in C</title><content type='html'>&lt;style type=&quot;text/css&quot;&gt;
  p {text-align: justify;}
  pre { color: #000000; background-color: #ffffff; }
  .code { color: #000000; background-color: #ffffff; }
  div.code { border: 1px dashed; margin: 5px; padding: 0px 5px;}
  .Constant { color: #c00058; }
  .PreProc { color: Magenta; }
  .Special { color: SlateBlue; }
  .Statement { color: Brown; }
  .Type { color: SeaGreen; }
&lt;/style&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;p&gt;Suppose you want to access a variable from several translation units. You would declare it in a header file:&lt;br /&gt;
&lt;/p&gt;&lt;code&gt;example.h&lt;/code&gt;&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;Type&quot;&gt;int&lt;/span&gt; foo;
&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You would optionally define it on a translation unit:&lt;br /&gt;
&lt;/p&gt;&lt;code&gt;example.c&lt;/code&gt;&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;Type&quot;&gt;int&lt;/span&gt; foo = &lt;span class=&quot;Constant&quot;&gt;2&lt;/span&gt;;
&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And you would refer to it on some other(s) translation unit(s):&lt;br /&gt;
&lt;/p&gt;&lt;code&gt;example-main.c&lt;/code&gt;&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;PreProc&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;Constant&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;

&lt;span class=&quot;PreProc&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;Constant&quot;&gt;&amp;quot;example.h&amp;quot;&lt;/span&gt;

&lt;span class=&quot;Type&quot;&gt;int&lt;/span&gt; main()
{
        printf(&lt;span class=&quot;Constant&quot;&gt;&amp;quot;foo = &lt;/span&gt;&lt;span class=&quot;Special&quot;&gt;%d&lt;/span&gt;&lt;span class=&quot;Special&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;Constant&quot;&gt;&amp;quot;&lt;/span&gt;, foo);

        &lt;span class=&quot;Statement&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;Constant&quot;&gt;0&lt;/span&gt;;
}
&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we compile and run the above we get:&lt;br /&gt;
&lt;/p&gt;&lt;code&gt;&lt;br /&gt;
$ gcc -Wall -o example example-main.c example.c&lt;br /&gt;
$ ./example&lt;br /&gt;
foo = 2&lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
&lt;p&gt;&lt;code&gt;&lt;span class=&quot;Type&quot;&gt;int&lt;/span&gt; foo;&lt;/code&gt; from &lt;code&gt;header.h&lt;/code&gt; is a &lt;em&gt;tentative definition&lt;/em&gt;. If you comment out the definition in &lt;code&gt;example.c&lt;/code&gt;, the tentative definition acts as a definition with an initializer of 0:&lt;br /&gt;
&lt;/p&gt;&lt;code&gt;&lt;br /&gt;
$ gcc -Wall -o example example-main.c example.c&lt;br /&gt;
$ ./example&lt;br /&gt;
foo = 0&lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
&lt;p&gt;But it can be considered to be better style to restrict header files to contain declarations, and not definitions, not even tentative ones. In that case, we would add a &lt;code&gt;extern&lt;/code&gt; storage specifier, which would turn our declaration on the header file from a tentative definition to a mere declaration:&lt;br /&gt;
&lt;/p&gt;&lt;code&gt;example.h&lt;/code&gt;&lt;br /&gt;
&lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;Type&quot;&gt;extern int&lt;/span&gt; foo;
&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In this case, if we don&#39;t define &lt;code&gt;foo&lt;/code&gt; in any translation unit, the linker will error out:&lt;br /&gt;
&lt;/p&gt;&lt;code&gt;&lt;br /&gt;
$ gcc -Wall -o example example-main.c example.c&lt;br /&gt;
/tmp/ccS3FMxx.o: In function `main&#39;:&lt;br /&gt;
example-main.c:(.text+0x1d): undefined reference to `foo&#39;&lt;br /&gt;
collect2: ld returned 1 exit status&lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
&lt;p&gt;All of the above is for C. C++ doesn&#39;t have tentative declarations, and therefore has some different rules on what constitutes a definition. In C++, &lt;code&gt;&lt;span class=&quot;Type&quot;&gt;int&lt;/span&gt; foo;&lt;/code&gt; constitutes a definition, while &lt;code&gt;&lt;span class=&quot;Type&quot;&gt;extern int&lt;/span&gt; foo;&lt;/code&gt; constitutes a declaration. So, if we leave out the &lt;code&gt;extern&lt;/code&gt; storage specifier in C++, the linker will error out:&lt;br /&gt;
&lt;/p&gt;&lt;code&gt;&lt;br /&gt;
$ g++ -Wall -o example example-main.cpp example.cpp&lt;br /&gt;
/tmp/cc8fzx4x.o:(.data+0x0): multiple definition of `foo&#39;&lt;br /&gt;
/tmp/ccxLfXPo.o:(.bss+0x0): first defined here&lt;br /&gt;
collect2: ld returned 1 exit status&lt;br /&gt;
&lt;/code&gt;</content><link rel='replies' type='application/atom+xml' href='http://ninjalj.blogspot.com/feeds/4778384965436099465/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ninjalj.blogspot.com/2011/10/tentative-definitions-in-c.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/462485765854905679/posts/default/4778384965436099465'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/462485765854905679/posts/default/4778384965436099465'/><link rel='alternate' type='text/html' href='http://ninjalj.blogspot.com/2011/10/tentative-definitions-in-c.html' title='Tentative Definitions in C'/><author><name>ninjalj</name><uri>http://www.blogger.com/profile/09820537051221341258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-462485765854905679.post-1343968471442448592</id><published>2011-09-23T00:36:00.000+02:00</published><updated>2011-09-23T00:36:35.930+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="propagation"/><category scheme="http://www.blogger.com/atom/ns#" term="spring"/><category scheme="http://www.blogger.com/atom/ns#" term="transactions"/><title type='text'>Spring @Transactional Propagation Reference</title><content type='html'>&lt;style type=&quot;text/css&quot;&gt;
  table {border-top: 1px solid; border-left: 1px solid;}
  th {border-right: 1px solid; border-bottom: 1px solid #333333;}
  td {border-right: 1px solid #888888; border-bottom: 1px solid #555555;}
  p {text-align: justify;}
&lt;/style&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;p&gt;Spring&#39;s propagation types for the &lt;code&gt;@Transactional&lt;/code&gt; annotation differ in how they behave in presence/absence of an existing transaction:&lt;br /&gt;
&lt;/p&gt;&lt;br /&gt;
&lt;table summary=&quot;table relating different propagation type behaviours when there exists/doesn&#39;t exist a current transaction&quot;&gt;  &lt;caption&gt;
    &lt;em&gt;Propagation types and their behaviour&lt;/em&gt;
  &lt;/caption&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;PROPAGATION TYPE&lt;/th&gt;
      &lt;th&gt;no current transaction&lt;/th&gt;
      &lt;th&gt;there&#39;s a current transaction&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;code&gt;MANDATORY&lt;/code&gt;&lt;/th&gt;
      &lt;td&gt;throw exception&lt;/td&gt;
      &lt;td&gt;use current transaction&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;code&gt;NEVER&lt;/code&gt;&lt;/th&gt;
      &lt;td&gt;don&#39;t create a transaction, run method outside any transaction&lt;/td&gt;
      &lt;td&gt;throw exception&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;code&gt;NOT_SUPPORTED&lt;/code&gt;&lt;/th&gt;
      &lt;td&gt;don&#39;t create a transaction, run method outside any transaction&lt;/td&gt;
      &lt;td&gt;suspend current transaction, run method outside any transaction&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;code&gt;SUPPORTS&lt;/code&gt;&lt;/th&gt;
      &lt;td&gt;don&#39;t create a transaction, run method outside any transaction&lt;/td&gt;
      &lt;td&gt;use current transaction&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;code&gt;REQUIRED&lt;/code&gt; (&lt;em&gt;default&lt;/em&gt;)&lt;/th&gt;
      &lt;td&gt;create a new transaction&lt;/td&gt;
      &lt;td&gt;use current transaction&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;code&gt;REQUIRES_NEW&lt;/code&gt;&lt;/th&gt;
      &lt;td&gt;create a new transaction&lt;/td&gt;
      &lt;td&gt;suspend current transaction, create a new independent transaction&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;code&gt;NESTED&lt;/code&gt;&lt;/th&gt;
      &lt;td&gt;create a new transaction&lt;/td&gt;
      &lt;td&gt;create a new nested transaction&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;br /&gt;
&lt;p&gt;It could be argued that &lt;code&gt;NEVER&lt;/code&gt; and &lt;code&gt;NOT_SUPPORTED&lt;/code&gt; (and arguably &lt;code&gt;SUPPORTS&lt;/code&gt; also) don&#39;t serve any useful purpose, and exist only for completeness; after all, why would you want to explicitly run something outside of any transaction?&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;As for the other propagation types, &lt;code&gt;REQUIRED&lt;/code&gt;/&lt;code&gt;MANDATORY&lt;/code&gt;/&lt;code&gt;SUPPORTS&lt;/code&gt; would be used when you want your code to be part of the current transaction, sharing its commit/rollback fate; &lt;code&gt;NESTED&lt;/code&gt; would come into use in cases where you want to be able to rollback only parts of a bigger transaction; and finally &lt;code&gt;REQUIRES_NEW&lt;/code&gt; is to be used when you want to do something totally unrelated to the current transaction.&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;The difference between &lt;code&gt;REQUIRED&lt;/code&gt;, &lt;code&gt;MANDATORY&lt;/code&gt; and &lt;code&gt;SUPPORTS&lt;/code&gt; strives in how they behave when there is no existing transaction. &lt;code&gt;MANDATORY&lt;/code&gt; acts as a sort of &lt;code&gt;assert&lt;/code&gt; directive, ensuring there &lt;i&gt;is&lt;/i&gt; an opened transaction. &lt;code&gt;REQUIRED&lt;/code&gt; creates a new transaction, being safe to use outside any transaction. &lt;code&gt;SUPPORTS&lt;/code&gt; rides along an existing transaction, but doesn&#39;t create a new one if none exists.&lt;br /&gt;
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://ninjalj.blogspot.com/feeds/1343968471442448592/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ninjalj.blogspot.com/2011/09/spring-transactional-propagation.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/462485765854905679/posts/default/1343968471442448592'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/462485765854905679/posts/default/1343968471442448592'/><link rel='alternate' type='text/html' href='http://ninjalj.blogspot.com/2011/09/spring-transactional-propagation.html' title='Spring &lt;code&gt;@Transactional&lt;/code&gt; Propagation Reference'/><author><name>ninjalj</name><uri>http://www.blogger.com/profile/09820537051221341258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-462485765854905679.post-1081145676517384917</id><published>2011-07-11T22:21:00.001+02:00</published><updated>2011-09-23T00:43:23.828+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cs-theory"/><category scheme="http://www.blogger.com/atom/ns#" term="regex"/><category scheme="http://www.blogger.com/atom/ns#" term="UNIX"/><title type='text'>Introduction to regexes</title><content type='html'>Let &lt;b&gt;Σ&lt;/b&gt; be an alphabet.&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;ε&lt;/b&gt; (the empty string) is a regular expression.&lt;/li&gt;
&lt;li&gt;If &lt;b&gt;a&lt;/b&gt; is a symbol from the alphabet &lt;b&gt;Σ&lt;/b&gt;, &lt;b&gt;a&lt;/b&gt; is a regular expression.&lt;/li&gt;
&lt;li&gt;If &lt;b&gt;a&lt;/b&gt; and &lt;b&gt;b&lt;/b&gt; are symbols from the alphabet &lt;b&gt;Σ&lt;/b&gt;, &lt;b&gt;ab&lt;/b&gt; (&lt;b&gt;a&lt;/b&gt; and &lt;b&gt;b&lt;/b&gt; concatenated) is a regular expression.&lt;/li&gt;
&lt;li&gt;If &lt;b&gt;a&lt;/b&gt; and &lt;b&gt;b&lt;/b&gt; are symbols from the alphabet &lt;b&gt;Σ&lt;/b&gt;, &lt;b&gt;a|b&lt;/b&gt; (&lt;b&gt;a&lt;/b&gt; or &lt;b&gt;b&lt;/b&gt;) is a regular expression.&lt;/li&gt;
&lt;li&gt;If &lt;b&gt;a&lt;/b&gt; is a symbol from the alphabet &lt;b&gt;Σ&lt;/b&gt;, &lt;b&gt;a*&lt;/b&gt; (&lt;b&gt;a&lt;/b&gt; repeated 0 or more times) is a regular expression.&lt;/li&gt;
&lt;/ul&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;A regular language is the language defined by a regular expression. A regular language is the language matched by a finite automaton. A word &lt;b&gt;w&lt;/b&gt; from a regular language can be recognized in &lt;b&gt;O(n)&lt;/b&gt;.&lt;/div&gt;&lt;br /&gt;
&lt;b&gt;Unix regexes:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;.&lt;/b&gt; means any character.&lt;/li&gt;
&lt;li&gt;Concatenation is represented without any symbol.&lt;/li&gt;
&lt;li&gt;Union (alternation) is represented by &lt;b&gt;|&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;*&lt;/b&gt; means Kleene closure (0 or more repetitions).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;+&lt;/b&gt; means 1 or more repetitions.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;?&lt;/b&gt; means 0 or 1 repetition.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;^&lt;/b&gt; means start of line.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;$&lt;/b&gt; means end of line.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;\&amp;lt;&lt;/b&gt; means start of word (in some programs).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;\&amp;gt;&lt;/b&gt; means end of word (in some programs).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;{&lt;/b&gt;&lt;i&gt;n&lt;/i&gt;&lt;b&gt;}&lt;/b&gt; means &lt;i&gt;n&lt;/i&gt; repetitions (in some programs).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;{,&lt;/b&gt;&lt;i&gt;m&lt;/i&gt;&lt;b&gt;}&lt;/b&gt; means from &lt;i&gt;0&lt;/i&gt; to &lt;i&gt;m&lt;/i&gt; repetitions (in some programs).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;{&lt;/b&gt;&lt;i&gt;n&lt;/i&gt;&lt;b&gt;,&lt;/b&gt;&lt;i&gt;m&lt;/i&gt;&lt;b&gt;}&lt;/b&gt; means from &lt;i&gt;n&lt;/i&gt; to &lt;i&gt;m&lt;/i&gt; repetitions (in some programs).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;a|b|c|d|e|f&lt;/b&gt; can be written as &lt;b&gt;[abcdef]&lt;/b&gt; or &lt;b&gt;[a-f]&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;a|b|c|d|h|i&lt;/b&gt; can be written as &lt;b&gt;[a-dhi]&lt;/b&gt; or &lt;b&gt;[a-dh-i]&lt;/b&gt;, ...&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[^&lt;/b&gt;&lt;i&gt;list&lt;/i&gt;&lt;b&gt;]&lt;/b&gt; matches characters not in &lt;i&gt;list&lt;/i&gt;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;()&lt;/b&gt; is used for grouping.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;\&lt;/b&gt; escapes special meaning of a metacharacter, e.g.: &lt;b&gt;\*&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;Precedence is: &lt;i&gt;repetition&lt;/i&gt;, &lt;i&gt;concatenation&lt;/i&gt;, &lt;i&gt;union&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
The supported regular expression syntax varies among programs, (e.g: &lt;i&gt;gawk&lt;/i&gt; vs &lt;i&gt;mawk&lt;/i&gt;, &lt;i&gt;vi&lt;/i&gt; vs &lt;i&gt;vim&lt;/i&gt;, ...).&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Back-references:&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;Many programs allow the use of &lt;b&gt;\&lt;/b&gt;&lt;i&gt;n&lt;/i&gt; (where &lt;i&gt;n&lt;/i&gt; is a number) to match a subexpression enclosed in &lt;b&gt;()&lt;/b&gt; or &lt;b&gt;\(\)&lt;/b&gt;, e.g: in &lt;i&gt;vim&lt;/i&gt;,  &lt;b&gt;\&amp;lt;\(.\)\(.\).\2\1\&amp;gt;&lt;/b&gt; matches five-letter palindromes. Regular expressions using these &lt;i&gt;back-references&lt;/i&gt; are no longer true regular expressions, and not all of them can be matched in &lt;b&gt;O(n)&lt;/b&gt; time.&lt;/div&gt;&lt;b&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;Regex/Regexp vs regular expressions:&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;Since modern regexes match things that cannot be matched with true regular expressions, it&#39;s been proposed (by Larry Wall) to call them regexes, not regular expressions. Perl regexes have been gaining expressive power through the years, and have grown, among many other things, support for look-around assertions, support for calling Perl code, and support for recursion. Many regex engines have taken things from Perl&#39;s regexes. On the other hand, Google&#39;s &lt;b&gt;re2&lt;/b&gt; library uses true regular expressions and a DFA-based implementation (in contrast to the NFA-based implementation of backtracking-regex engines) to achieve very high performance.&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ninjalj.blogspot.com/feeds/1081145676517384917/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ninjalj.blogspot.com/2011/07/introduction-to-regexes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/462485765854905679/posts/default/1081145676517384917'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/462485765854905679/posts/default/1081145676517384917'/><link rel='alternate' type='text/html' href='http://ninjalj.blogspot.com/2011/07/introduction-to-regexes.html' title='Introduction to regexes'/><author><name>ninjalj</name><uri>http://www.blogger.com/profile/09820537051221341258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-462485765854905679.post-9196959520774754114</id><published>2011-07-03T13:37:00.001+02:00</published><updated>2011-07-03T13:55:52.689+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="clone"/><category scheme="http://www.blogger.com/atom/ns#" term="fork"/><category scheme="http://www.blogger.com/atom/ns#" term="Linux"/><category scheme="http://www.blogger.com/atom/ns#" term="non-MMU"/><category scheme="http://www.blogger.com/atom/ns#" term="POSIX"/><category scheme="http://www.blogger.com/atom/ns#" term="UNIX"/><category scheme="http://www.blogger.com/atom/ns#" term="vfork"/><title type='text'>vfork()</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;There are some limitations to using non-MMU CPUs in *nix, e.g: there are restrictions to &lt;code&gt;fork()&lt;/code&gt;, &lt;code&gt;mmap()&lt;/code&gt;, &lt;code&gt;shmat()&lt;/code&gt; and &lt;code&gt;brk()&lt;/code&gt;. Let&#39;s talk about &lt;code&gt;fork()&lt;/code&gt;.&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;code&gt;fork(2)&lt;/code&gt; creates a child process with a copy of the memory of the current process (and a copy of the file descriptors, signal handlers, filesystem namespace, ...) This copy has the same virtual addresses as those used on the parent. In a CPU with a MMU, the MMU translates each process&#39; virtual addresses to different physical addresses, so everything works and everyone is happy.&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;However, in a MMU-less CPU, virtual addresses are the same as physical addresses (said another way, there are no virtual addresses), so &lt;code&gt;fork()&lt;/code&gt; cannot work in a MMU-less system in the general case (at least in an efficient manner, you can always move processes in memory at each context switch).&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Often, &lt;code&gt;fork(2)&lt;/code&gt; is used to immediately call &lt;code&gt;execve(2)&lt;/code&gt; in the child. There is a special system call fot this: &lt;code&gt;vfork(2)&lt;/code&gt;. Typically, &lt;code&gt;vfork()&lt;/code&gt; doesn&#39;t create a new copy of the parent&#39;s memory, but uses the parent&#39;s memory. It&#39;s also typical for the parent to remain blocked until the child calls &lt;code&gt;execve()&lt;/code&gt; or &lt;code&gt;_exit()&lt;/code&gt;.&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;The only safe things you can do after &lt;code&gt;vfork()&lt;/code&gt; on the child are the following:&lt;/div&gt;&lt;ul&gt;&lt;li&gt;Calling &lt;code&gt;execve()&lt;/code&gt;.&lt;/li&gt;
&lt;li style=&quot;text-align: justify;&quot;&gt;Calling &lt;code&gt;_exit()&lt;/code&gt; (Note it&#39;s &lt;code&gt;_exit()&lt;/code&gt;, not &lt;code&gt;exit()&lt;/code&gt;, &lt;code&gt;exit()&lt;/code&gt; can run C library finalization code, such as closing and freeing file handles, which in &lt;code&gt;vfork()&lt;/code&gt; implementations using the parent&#39;s memory would also close and free them for the parent, leading to very bad things).&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;pid_t&lt;/code&gt; value returned by &lt;code&gt;vfork()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Of course, &lt;code&gt;vfork()&lt;/code&gt; can be implemented simply as:&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;code&gt;#define vfork fork&lt;/code&gt;&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;As &lt;code&gt;vfork()&lt;/code&gt; uses a shared address space, it works perfectly fine on non-MMU CPUs. Also, creating a child to immediately call &lt;code&gt;execve()&lt;/code&gt; is a very common use of &lt;code&gt;fork()/vfork()&lt;/code&gt;.&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;The other *nix classical API to create processes/threads/tasks is &lt;code&gt;pthread_create()&lt;/code&gt;. As the different threads share the memory address space, this works for non-MMU CPUs. POSIX also introduces a &lt;code&gt;posix_spawn()&lt;/code&gt; function.&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;In the specific case of Linux, there is also &lt;code&gt;clone(2)&lt;/code&gt;. In non-MMU CPUs, &lt;code&gt;clone()&lt;/code&gt; works fine if it&#39;s passed the &lt;code&gt;CLONE_VM&lt;/code&gt; flag.&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;An interesting detail in &lt;code&gt;vfork()&lt;/code&gt; (explained by Jamie Loker at uclinux-dev at &lt;a href=&quot;http://www.mail-archive.com/uclinux-dev@uclinux.org/msg01290.html&quot;&gt;http://www.mail-archive.com/uclinux-dev@uclinux.org/msg01290.html&lt;/a&gt;) is how it&#39;s implemented in uClibc:&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;code&gt;&lt;br /&gt;
__vfork:&lt;br /&gt;
popl %ecx&lt;br /&gt;
movl $__NR_vfork,%eax&lt;br /&gt;
int $0x80&lt;br /&gt;
pushl %ecx&lt;br /&gt;
cmpl $-4095,%eax&lt;br /&gt;
jae __syscall_error&lt;br /&gt;
ret&lt;br /&gt;
&lt;/code&gt;&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;When you call &lt;code&gt;vfork()&lt;/code&gt;, Linux first returns control to the child. The parent hasn&#39;t yet returned from &lt;code&gt;vfork()&lt;/code&gt;. The call to &lt;code&gt;execve()&lt;/code&gt; in the child can corrupt &lt;code&gt;vfork()&lt;/code&gt;&#39;s stack frame in the parent.&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;The solution is not depending on &lt;code&gt;vfork()&lt;/code&gt;&#39;s stack frame. In the previous i386 example, the first thing that is done is save the return address (which is the only think saved on &lt;code&gt;vfork()&lt;/code&gt;&#39;s stack frame, as &lt;code&gt;vfork()&lt;/code&gt; has neither parameters nor local variables) in a register, where it is safe. The &lt;code&gt;int $0x80&lt;/code&gt; instruction is the one to pass control to &lt;code&gt;sys_vfork()&lt;/code&gt; at the kernel. On return from &lt;code&gt;sys_vfork()&lt;/code&gt;, we push the return address into the stack frame again, check for errors, and return from &lt;code&gt;vfork()&lt;/code&gt;.&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;(Originally published at &lt;a href=&quot;http://barrapunto.com/%7Eninjalj/journal/27731&quot;&gt;http://barrapunto.com/~ninjalj/journal/27731&lt;/a&gt; (in Spanish))&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ninjalj.blogspot.com/feeds/9196959520774754114/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ninjalj.blogspot.com/2011/07/vfork.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/462485765854905679/posts/default/9196959520774754114'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/462485765854905679/posts/default/9196959520774754114'/><link rel='alternate' type='text/html' href='http://ninjalj.blogspot.com/2011/07/vfork.html' title='vfork()'/><author><name>ninjalj</name><uri>http://www.blogger.com/profile/09820537051221341258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-462485765854905679.post-4957608322760253961</id><published>2011-07-02T15:57:00.004+02:00</published><updated>2011-07-03T14:00:31.627+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="arithmetic-conversions"/><category scheme="http://www.blogger.com/atom/ns#" term="C"/><category scheme="http://www.blogger.com/atom/ns#" term="C99"/><category scheme="http://www.blogger.com/atom/ns#" term="integer-promotions"/><title type='text'>Integer Promotions and Conversions in C</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;Suppose you have the following code:&lt;/div&gt;&lt;pre&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

int main()
{
    unsigned x = 1;
    char y = -1;

    if (x &amp;gt; y)
        printf(&quot;x &amp;gt; y\n&quot;);
    else
        printf(&quot;x &amp;lt;= y\n&quot;);

    return 0;
}&lt;/code&gt;&lt;/pre&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;What does really happen here? Since we are dealing with integer types, first the integer promotions are applied, and then the arithmetic conversions are applied.&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;If &lt;code&gt;char&lt;/code&gt; is equivalent to &lt;code&gt;signed char&lt;/code&gt;:&lt;/div&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;&lt;code&gt;char&lt;/code&gt; is promoted to &lt;code&gt;int&lt;/code&gt; (Integer Promotions, ISO C99 §6.3.1.1 ¶2)&lt;/li&gt;
&lt;li&gt;Since &lt;code&gt;int&lt;/code&gt; and &lt;code&gt;unsigned&lt;/code&gt; have the same rank, &lt;code&gt;int&lt;/code&gt; is converted to &lt;code&gt;unsigned&lt;/code&gt; (Arithmetic  Conversions, ISO C99 §6.3.1.8)&lt;/li&gt;
&lt;/ul&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;If &lt;code&gt;char&lt;/code&gt; is equivalent to &lt;code&gt;unsigned char&lt;/code&gt;:&lt;/div&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;&lt;code&gt;char&lt;/code&gt; may be promoted to either &lt;code&gt;int&lt;/code&gt; or &lt;code&gt;unsigned int&lt;/code&gt;: &lt;ul&gt;&lt;li&gt;If &lt;code&gt;int&lt;/code&gt; can represent all &lt;code&gt;unsigned char&lt;/code&gt; values (typically because &lt;code&gt;sizeof(int) &amp;gt; sizeof(char)&lt;/code&gt;), &lt;code&gt;char&lt;/code&gt; is converted to &lt;code&gt;int&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Otherwise (typically because &lt;code&gt;sizeof(char)==sizeof(int)&lt;/code&gt;), &lt;code&gt;char&lt;/code&gt; is converted to &lt;code&gt;unsigned&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Now we have one operand that is either &lt;code&gt;int&lt;/code&gt; or &lt;code&gt;unsigned&lt;/code&gt;, and another that is &lt;code&gt;unsigned&lt;/code&gt;. The first operand is converted to &lt;code&gt;unsigned&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;The rules that are applied are the following:&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;b&gt;Integer promotions&lt;/b&gt;:  An expression of a type of lower rank that &lt;code&gt;int&lt;/code&gt; is converted to &lt;code&gt;int&lt;/code&gt; if &lt;code&gt;int&lt;/code&gt; can hold all of the values of the original type, to &lt;code&gt;unsigned&lt;/code&gt; otherwise.&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;b&gt;Arithmetic conversions&lt;/b&gt;: Try to convert to the larger type. When there is conflict between signed and unsigned, if the larger (including the case where the two types have the same rank) type is unsigned, go with unsigned. Otherwise, go with signed only in the case it can represent all the values of both types.&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;b&gt;Conversions between integer types&lt;/b&gt;(ISO C99 §6.3.1.3):&lt;/div&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;Conversion of an out-of-range value to an unsigned integer type is done via wrap-around (modular arithmetic).&lt;/li&gt;
&lt;li&gt;Conversion of an out-of-range value to a signed integer type is implementation defined, and can raise a signal (such as SIGFPE).&lt;/li&gt;
&lt;/ul&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;b&gt;Ranks&lt;/b&gt;: Every type has a rank. unsigned types have the same rank as the corresponding signed type. Ranks satisfy the following: &lt;code&gt;char &amp;lt; short &amp;lt; int &amp;lt; long &amp;lt; long long&lt;/code&gt;.&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;b&gt;Representation of integer types&lt;/b&gt;:&lt;/div&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;Signed types consist of sign bits, padding bits and value bits.&lt;/li&gt;
&lt;li&gt;Unsigned types consists of padding bits and value bits.&lt;/li&gt;
&lt;li&gt;An unsigned type has to have a number of value bits greater or equal to the number of value bits of its corresponding signed type.&lt;/li&gt;
&lt;/ul&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Now we can rephrase part of the above as:&lt;/div&gt;&lt;ul style=&quot;text-align: justify;&quot;&gt;&lt;li&gt;&lt;code&gt;unsigned char&lt;/code&gt; may be promoted to either &lt;code&gt;int&lt;/code&gt; or &lt;code&gt;unsigned int&lt;/code&gt;: &lt;ul&gt;&lt;li&gt;If &lt;code&gt;int&lt;/code&gt; can represent all &lt;code&gt;unsigned char&lt;/code&gt; values (because the number of value bits of &lt;code&gt;int &amp;gt;=&amp;nbsp;&lt;/code&gt;number of value bits of&lt;code&gt; unsigned char&lt;/code&gt;), &lt;code&gt;unsigned char&lt;/code&gt; is converted to &lt;code&gt;int&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Otherwise (because the number of value bits of &lt;code&gt;int &amp;lt;&amp;nbsp;&lt;/code&gt;number of value bits of&lt;code&gt; unsigned char&lt;/code&gt;&lt;code&gt;&lt;/code&gt;), &lt;code&gt;unsigned char&lt;/code&gt; is converted to &lt;code&gt;unsigned&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;Borderline example: a system with an &lt;code&gt;unsigned char&lt;/code&gt; type with 1 padding bit and 31 value bits, and an &lt;code&gt;int&lt;/code&gt; type with 1 sign bit and 31 value bits would fall into the first condition (and be an exception to the previous rule of thumb using &lt;code&gt;sizeof()&lt;/code&gt;).&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ninjalj.blogspot.com/feeds/4957608322760253961/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ninjalj.blogspot.com/2011/07/integer-promotions-and-conversions-in-c.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/462485765854905679/posts/default/4957608322760253961'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/462485765854905679/posts/default/4957608322760253961'/><link rel='alternate' type='text/html' href='http://ninjalj.blogspot.com/2011/07/integer-promotions-and-conversions-in-c.html' title='Integer Promotions and Conversions in C'/><author><name>ninjalj</name><uri>http://www.blogger.com/profile/09820537051221341258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-462485765854905679.post-4571065695911513965</id><published>2011-06-25T17:06:00.005+02:00</published><updated>2011-07-03T14:03:45.764+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C"/><category scheme="http://www.blogger.com/atom/ns#" term="Linux"/><category scheme="http://www.blogger.com/atom/ns#" term="POSIX"/><category scheme="http://www.blogger.com/atom/ns#" term="termios"/><category scheme="http://www.blogger.com/atom/ns#" term="tty"/><category scheme="http://www.blogger.com/atom/ns#" term="UNIX"/><title type='text'>Character by Character Input on *nix</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;A frequently asked question is how to read a single key on *nix. Many people expect &lt;code&gt;read(2)&lt;/code&gt; of a single byte to return immediately, but by default it doesn&#39;t.&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;On Unix you don&#39;t deal with keyboards, you deal with a terminal. A terminal can be the physical console, a terminal (or terminal emulator) on a serial port, an xterm, ...&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;By default, input lines are not made available to programs until the terminal (or terminal emulator) sees a line delimiter.&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;On POSIX, terminals are controlled by the &lt;code&gt;termios(3)&lt;/code&gt; functions. These include &lt;code&gt;tcgetattr(3)&lt;/code&gt; and &lt;code&gt;tcsetattr(3)&lt;/code&gt;, which can be used to modify terminal attributes. These include input modes, output modes, and local modes.&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;One of the local modes is &lt;em&gt;canonical mode&lt;/em&gt; (enabled by default), in which input is made available line by line, and certain line editing characters are enabled.&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;text-align: justify;&quot;&gt;So, to read input character by character, you need to do something like the following:&lt;/div&gt;&lt;pre&gt;&lt;code&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;errno.h&amp;gt;

#include &amp;lt;unistd.h&amp;gt;
#include &amp;lt;poll.h&amp;gt;
#include &amp;lt;signal.h&amp;gt;
#include &amp;lt;termios.h&amp;gt;
#include &amp;lt;sys/ioctl.h&amp;gt;

static volatile sig_atomic_t end = 0;

static void sighandler(int signo)
{
        end = 1;
}

int main()
{
        struct termios oldtio, curtio;
        struct sigaction sa;

        /* Save stdin terminal attributes */
        if (tcgetattr(0, &amp;amp;oldtio) &amp;lt; 0) {
                perror(&quot;tcgetattr&quot;);
                exit(1);
        }

        /* Make sure we exit cleanly */
        memset(&amp;amp;sa, 0, sizeof(struct sigaction));
        sa.sa_handler = sighandler;
        if (sigaction(SIGINT, &amp;amp;sa, NULL) &amp;lt; 0) {
                perror(&quot;sigaction&quot;);
                exit(1);
        }
        if (sigaction(SIGQUIT, &amp;amp;sa, NULL) &amp;lt; 0) {
                perror(&quot;sigaction&quot;);
                exit(1);
        }
        if (sigaction(SIGTERM, &amp;amp;sa, NULL) &amp;lt; 0) {
                perror(&quot;sigaction&quot;);
                exit(1);
        }

        /* This is needed to be able to tcsetattr() after a hangup (Ctrl-C)
         * see tcsetattr() on POSIX
         */
        memset(&amp;amp;sa, 0, sizeof(struct sigaction));
        sa.sa_handler = SIG_IGN;
        if (sigaction(SIGTTOU, &amp;amp;sa, NULL) &amp;lt; 0) {
                perror(&quot;sigaction&quot;);
                exit(1);
        }

        /* Set non-canonical no-echo for stdin */
        if (tcgetattr(0, &amp;amp;curtio) &amp;lt; 0) {
                perror(&quot;tcgetattr&quot;);
                exit(1);
        }
        curtio.c_lflag &amp;amp;= ~(ICANON | ECHO);
        /* This could be interrupted by a signal if it used
         * TCSADRAIN or TCSAFLUSH, but it wouldn&#39;t matter, since
         * we would have not changed terminal attributes yet
         */
        if (tcsetattr(0, TCSANOW, &amp;amp;curtio) &amp;lt; 0) {
                perror(&quot;tcsetattr&quot;);
                exit(1);
        }
        if (tcgetattr(0, &amp;amp;curtio) &amp;lt; 0) {
                perror(&quot;tcgetattr&quot;);
                exit(1);
        }
        if (curtio.c_lflag &amp;amp; (ICANON | ECHO)) {
                fprintf(stderr, &quot;couldn&#39;t set non-canonical no-echo mode\n&quot;);
                exit(1);
        }

        /* main loop */
        while (!end) {
                struct pollfd pfds[1];
                int ret;
                char c;

                /* See if there is data available */
                pfds[0].fd = 0;
                pfds[0].events = POLLIN;
                ret = poll(pfds, 1, 0);
                if (ret &amp;lt; 0 &amp;amp;&amp;amp; errno != EINTR) {
                        perror(&quot;poll&quot;);
                        exit(1);
                }

                /* Consume data */
                if (ret &amp;gt; 0) {
                        printf(&quot;Data available\n&quot;);
                        if (read(0, &amp;amp;c, 1) &amp;lt; 0 &amp;amp;&amp;amp; errno != EINTR) {
                                perror(&quot;read&quot;);
                                exit(1);
                        }
                }
        }

        /* restore terminal attributes */
        /* This could be interrupted by a signal if it used TCSADRAIN
         * or TCSAFLUSH
         */
        if (tcsetattr(0, TCSANOW, &amp;amp;oldtio) &amp;lt; 0) {
                perror(&quot;tcsetattr&quot;);
                exit(1);
        }

        return 0;
}
&lt;/code&gt;&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://ninjalj.blogspot.com/feeds/4571065695911513965/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ninjalj.blogspot.com/2011/06/frequently-asked-question-is-how-to.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/462485765854905679/posts/default/4571065695911513965'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/462485765854905679/posts/default/4571065695911513965'/><link rel='alternate' type='text/html' href='http://ninjalj.blogspot.com/2011/06/frequently-asked-question-is-how-to.html' title='Character by Character Input on *nix'/><author><name>ninjalj</name><uri>http://www.blogger.com/profile/09820537051221341258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>