ajfabbri
BAN USERYou can observe that command at the system call layer by putting the command in a file (test.bash), and then running through strace:
$ strace -f -o /tmp/my.output bash test.bash
Some highlights:
- You will see your strace command running the bash executable via the exec syscall
execve("/bin/bash")
- The bash process will read the text file and interpret the commands.
- This bash process will create a pipe to read output from the subshell that $(command) creates
pipe([3,4])
.
- The bash proces will call fork() (clone in linux) to create a subprocess for the subshell
clone(...)
- Parent process does a blocking read on the first file descriptor of the pipe (waiting to read output from the subshell)
read(3, <unfinished ...>
- The new child process will use the second fd in the pipe for it's new stdout
dup2(4, 1)
- That new child pid will look for ls in the system path, then call exec() to run ls in the subshell process
execve("/bin/ls", ["ls"], [/* 22 vars */]) = 0
- The ls program uses open() to open the current directory, then readdir() / getdents() to read the directory entries:
26849 openat(AT_FDCWD, ".", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3
26849 getdents(3, /* 13 entries */, 32768) = 416
26849 getdents(3, /* 0 entries */, 32768) = 0
- Next, the ls command writes to stdout
write(1, "file1"..., 128) = 128
- This wakes up the parent process blocked on the pipe (since child fd 1 is stdout, which was dup2'd to the second pipe fd 4)
26848 <... read resumed> "file1"..., 128) = 128
- The parent process waits for the child to exit, in case it hasn't already
wait4(-1, 0x7fff2eeb2398, WNOHANG, NULL)
It depends on the compiler, which tries to optimize layout for the target architecture.
- ajfabbri May 16, 2014So the answer will vary. Saying there is one answer is wrong, IMO. Compilers have a certain degree of freedom here, and the behavior can also be changed with command line args.
The ISO C standard does not specify required struct sizes, but it does have rules about alignment. (i.e. alignment of a struct has to be a multiple of smallest common multiple of the field alignments).
This is why, if you require a certain packing (as protocol stack and hardware driver structs often do), you may need to add compiler extensions to specify the alignment you need.
For examples, see the packed, align, and bitwise attributes for GCC. They are used throughout the linux kernel.