-
Notifications
You must be signed in to change notification settings - Fork 323
Using the lsof command
If you’re running Mac or Linux, you will already have this command installed. lsof
tells you what a process is currently talking to. It will list the process’ network connections and which files it’s reading. That’s really useful if, say, you want to see exactly what the adb
server process is doing.
But the cool thing is that the Android designers helpfully included a copy of lsof
inside every Android device.
Let’s begin by running lsof
on a development machine. Let’s take a look at a machine that has an AVD running:
$ adb devices
List of devices attached
emulator-5554 device
$
The adb
command finds out which devices are connected by running a background copy of itself called the adb daemon. You can find the daemon using the ps
command:
$ ps -ef | grep adb
501 42769 1 0 7:16pm ?? 0:00.31 adb -P 5037 fork-server server
501 42869 42797 0 7:19pm ttys000 0:00.00 grep adb
$
Here we can see the daemon running as process number 42769, and it was started with adb -P 5037 fork-server server
. We’ll see in a moment that the -P 5037
option tells the server to listen on port 5037.
Now we can use the lsof
command to look in a little more detail at what the adb
server is doing:
$ lsof -p 42769
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
adb 42769 davidg cwd DIR 1,4 442 3815029 /Applications/Android Studio.app/Contents/bin
adb 42769 davidg txt REG 1,4 1324340 3828228 /Users/davidg/Library/Android/sdk/platform-tools/adb
adb 42769 davidg txt REG 1,4 622896 14974080 /usr/lib/dyld
...
adb 42769 davidg 9u IPv4 0x27ac4f6f27541281 0t0 TCP localhost:5037->localhost:51686 (ESTABLISHED)
adb 42769 davidg 10u IPv4 0x27ac4f6f2749b9b1 0t0 TCP localhost:5037->localhost:51691 (ESTABLISHED)
...
$
The lsof
command shows a lot more output than you can see here. Each line in the output represents something that the server process is reading from or writing to. The lines with a NODE
value of TCP
represent network connections. One of the examples above shows a connection going from port 5037 on the server to some other process on port 51686. We can find what that other process is like this:
$ lsof | grep 51686
studio 42696 davidg 487u IPv4 0x27ac4f6f2a7709b1 0t0 TCP localhost:51686->localhost:5037 (ESTABLISHED)
adb 42769 davidg 9u IPv4 0x27ac4f6f27541281 0t0 TCP localhost:5037->localhost:51686 (ESTABLISHED)
$
Running lsof
without any options, will output every connection made by every process. By searching through all of that and looking for 51686
, we find that the network connection is to a copy of Android Studio. So we know that our IDE is communicating with the adb
server over a network socket.
You can also run lsof
on an Android device. If you’re investigating how Android works, it’s actually easier to do it by running a Android Virtual Device than by connecting a physical device. Why? Because the virtual device will give you permission to do just about anything.
You can run a command on an Android device by either:
- Starting a shell on the device with
adb shell
and then typing the command in direct, or - Passing the command as an additional string on the end of the
adb shell
command.
We’re going to use the second option. This is how we’ll run lsof
on the Android device:
$ adb shell lsof
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
init 1 root exe ??? ??? ??? ??? /init
init 1 root 0 ??? ??? ??? ??? /dev/__null__ (deleted)
init 1 root 1 ??? ??? ??? ??? /dev/__null__ (deleted)
init 1 root 2 ??? ??? ??? ??? /dev/__null__ (deleted)
init 1 root 3 ??? ??? ??? ??? /dev/__kmsg__ (deleted)
init 1 root 4 ??? ??? ??? ??? /dev/__properties__
init 1 root 5 ??? ??? ??? ??? socket:[2438]
init 1 root 6 ??? ??? ??? ??? socket:[2440]
...
lsof 2727 root mem ??? 1f:00 4096 848 /system/lib/libnetd_client.so
lsof 2727 root mem ??? 1f:00 8192 848 /system/lib/libnetd_client.so
lsof 2727 root mem ??? 00:0d 0 2216 /dev/__properties__
lsof 2727 root mem ??? 1f:00 0 867 /system/lib/libselinux.so
lsof 2727 root mem ??? 1f:00 94208 867 /system/lib/libselinux.so
lsof 2727 root mem ??? 1f:00 98304 867 /system/lib/libselinux.so
lsof 2727 root mem ??? 1f:00 0 787 /system/lib/libcutils.so
This output is a lot longer than we’re showing here. The lsof
command within the device does not take any additional options, so it always outputs every connection on every process. But again, we can use other command line tools to cut the data down a little.
$ adb shell lsof | grep adb
adbd 943 root exe ??? ??? ??? ??? /sbin/adbd
adbd 943 root 0 ??? ??? ??? ??? /dev/null
adbd 943 root 1 ??? ??? ??? ??? /dev/null
adbd 943 root 2 ??? ??? ??? ??? /dev/null
adbd 943 root 3 ??? ??? ??? ??? /dev/qemu_pipe
adbd 943 root 4 ??? ??? ??? ??? socket:[2503]
adbd 943 root 5 ??? ??? ??? ??? socket:[2504]
...
adbd 943 root 73 ??? ??? ??? ??? socket:[7880]
adbd 943 root 74 ??? ??? ??? ??? socket:[7888]
adbd 943 root 75 ??? ??? ??? ??? socket:[7936]
adbd 943 root 77 ??? ??? ??? ??? socket:[7963]
adbd 943 root mem ??? 00:01 0 2101 /sbin/adbd
adbd 943 root mem ??? 00:01 589824 2101 /sbin/adbd
adbd 943 root mem ??? 00:01 598016 2101 /sbin/adbd
$
Here we can see that there’s another adb
-like process running inside the Android device. This one is called adbd
, and in fact it’s the other end of the communication channel from the adb
server process on the development machine. See that /dev/qemu_pipe
line? That’ll be a virtual device in the QEMU emulator that’s communicating with the adb
process on the development machine.
In this way, you can use lsof
to track down the private communication channels between processes, and unveiling exactly how things talk to each other.
This page is part of the support material for the book Head First Android Development
To find out more, go to https://dogriffiths.github.io/HeadFirstAndroid/