15

I would like to know exactly how the "Is" command works in Linux and Unix.

As far as I know, ls forks & exec to the Linux/Unix shell and then gets the output (of the current file tree. eg./home/ankit/). I need a more detailed explanation, as I am not sure about what happens after calling fork.

Could anyone please explain the functionality of the 'ls' command in detail?

Lin Du
  • 88,126
  • 95
  • 281
  • 483
Ankit Singh
  • 2,602
  • 6
  • 32
  • 44

5 Answers5

42

ls doesn't fork. The shell forks and execs in order to run any command that isn't built in, and one of the commands it can run is ls.

ls uses opendir() and readdir() to step through all the files in the directory. If it needs more information about one of them it calls stat().

Mark Baker
  • 5,588
  • 2
  • 27
  • 25
  • 1
    As a point of interest, I think you'll find it stat()'s just about every file in the directory, especially if colors and/or file type pre/suffixs are turned on. – Matthew Scharley Oct 15 '08 at 10:01
  • On a different note, why does the shell need to fork for foreground processes? – Matthew Scharley Oct 15 '08 at 10:02
  • 2
    monoxide: an exec() without a fork() will replace the currently running process, which means your shell would vanish the first time you ran a command. – Greg Hewgill Oct 15 '08 at 10:04
  • Thanks Mark, here is the decelaration part from K&RC to help others. DIR *opendir(char *dirname); Dirent *readdir(DIR *dfd); void closedir(DIR *dfd); – Ankit Singh Oct 15 '08 at 10:38
  • if ls is a built-in, like in some standalone shells, does it still fork and exec? – warren Oct 15 '08 at 13:28
  • If it is built-in, it does not need to start another program, so an exec() is not required. Whether it fork()s or not depends on the shell and the situation -- for example, if `cat` was built-in, it would still be easier to fork to handle something like `cat | cat`, but forked `read` is hard. – ephemient Oct 15 '08 at 14:16
  • 1
    @Mark: it also uses lstat() since otherwise it only sees the permissions of the file at the far end of a symlink and not the symlink itself. – Jonathan Leffler Oct 19 '08 at 02:47
  • 1
    @monoxide: the shell can run other programs in exactly one of two ways - by using exec() to replace itself with the other program, or by using fork() and then exec(). Those are the only mechanisms available in Unix (unless you count pthread_spawn()). – Jonathan Leffler Oct 19 '08 at 02:48
  • 1
    jonathan, the pthread library is based on the clone() system call (in linux - other unix versions with kernel threading will have something similar but probably not identical). Using clone() directly and then exec() is another way you could launch a program, though not one that's useful in practice. – Mark Baker Oct 20 '08 at 16:00
11

To add to the answer, in The C Programming Language book (K&RC) they have given a small example on how to go about implementing ls. They have explained the datastructures and functions used very well.

Sushant
  • 1,013
  • 1
  • 11
  • 20
4

To understand what ls does, you could take a gander at the OpenSolaris source: https://hg.java.net/hg/solaris~on-src/file/tip/usr/src/cmd/ls/ls.c.

If that´s overwhelming, on Solaris you start by using truss to look at the system calls that ls makes to understand what it does. Using truss, try:

truss -afl -o ls.out /bin/ls

then look at the output in ls.out

I believe that trace is the equivalent to truss in Linux.

alanc
  • 4,102
  • 21
  • 24
tpgould
  • 1,746
  • 10
  • 10
3

If you really want to understand the detailed innards of ls, look at the source code. You can follow tpgould's link to the Solaris source, or it's easy to find the source online from any Linux or BSD distribution.

I'll particularly recommend the 4.4BSD source.

As I recall, ls starts by parsing its many options, then starts with the files or directories listed on the command line (default is "."). Subdirectories are handled by recursion into the directory list routine. There's no fork() or exec() that I recall.

mpez0
  • 2,815
  • 17
  • 12
  • Complete C newbie who woke up one morning wondering how C works. Is this the 4.4BSD file in question? (Obviously it'll be a while before I'm at the point of being able to make sense of it but gotta start somewhere…) https://github.com/sergev/4.4BSD-Lite2/blob/master/usr/src/bin/ls/ls.c – henry May 18 '17 at 18:03
  • @henry That's the file, though it (or any other ls.c) is probably too complex for a "complete C newbie" using it for study. – mpez0 Jul 09 '17 at 20:36
  • Yes definitely won't be understanding this any time soon, but at least I know the goal. Thanks! – henry Jul 10 '17 at 15:11
-1

This is a old thread , but still I am commenting because I believe the answer which was upvoted and accepted is partially incorrect. @Mark says that ls is built into shell so shell doesn't exec and fork. When I studied the tldp document on bash(I have attached the link) "ls" is not listed as a build in command.

http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_01_03.html

Bash built-in commands:

alias, bind, builtin, command, declare, echo, enable, help, let, local, logout, printf, read, shopt, type, typeset, ulimit and unalias.

Raghupathy
  • 823
  • 1
  • 9
  • 21
  • 3
    I think you're misunderstanding the original answer and in heated agreement with it. The question stated "ls forks & exec to the linux/unix shell" to which the answer correctly replied "ls doesn't fork. The shell forks and execs" and went on to say that ls is one of the commands the shell forks/execs. – alanc Dec 19 '11 at 03:05
  • 1
    @alanc Thanks for clarification. Up voting the accepted answer :) – Raghupathy Dec 19 '11 at 13:11