How to do like netstat -p, but faster?
Take a look at this answer, where various methods and programs that perform socket to process mappings are mentioned. You might also try several additional techniques to improve performance:
- Caching the file descriptors in
/proc
, and the information in/proc/net
. This is done by the programs mentioned in the linked answer, but is only viable if your process lasts more than a few seconds. - You might try
getpeername()
, but this relies you knowing of the possible endpoints and what processes they map to. Your questions suggests that you are connecting sockets locally, you might try using Unix sockets which allow you to receive the credentials of a peer when exchanging messages by passingSO_PASSCRED
tosetsockopt()
. Take a look at these examples (they're pretty nasty but the best I could find).- http://www.lst.de/~okir/blackhats/node121.html
- http://www.zanshu.com/ebook/44_secure-programming-cookbook-for-c-and-cpp/0596003943_secureprgckbk-chp-9-sect-8.html
- Take a look at
fs/proc/base.c
in the Linux kernel. This is the heart of the information given by the result of a readlink on a file descriptor in/proc/PID/fd/FD
. A significant part of the overhead is the passing of the requests up and down the VFS layer, the numerous locking that occurs on all the kernel data structures that provide the information given, and the stringyfying and destringyfying at the kernel and your end respectively. You might adapt some of the code in this file to generate this information without many of the intermediate layers, in particular minimizing the locking to once per process, or simply once per scan of the entire data set you're after.
My personal recommendation is to just brute force it for now, ideally traverse the processes in /proc
in reverse numerical order, as the more recent and interesting processes will have higher PIDs, and return as soon as you've located the results you're after. Doing this once per incoming connection is relatively cheap, it really depends on how performance critical your application is. You'll definitely find it worthwhile to bypass calling netstat
and directly parse the new connection from /proc/net/PROTO
, then locate the socket in /proc/PID/fd
. If all your traffic is localhost, just switch to Unix sockets and get the credentials directly. Writing a new syscall or proc module that dumps huge amounts of data regarding file descriptors I'd save for last.
How I can get ports associated to the application that opened them?
I was hoping a cleverer answer would appear. I did just this (programmatically in Python), in an attempt to rewrite a program called NetHogs. My version is here, specifically here is the module in Python used to parse the table from /proc
. If you're not Python literate (go learn it), then take a look at the original NetHogs, which uses a blend of C/C++ (and is a bit painful to read hence the rewrite).
It's worth noting that extensive or quickly repeated attempts to parse socket information from /proc
is very CPU intensive, as the operating system has to handle every syscall made, and parse internal structures dynamically. As such you'll find some caching, and timing assumptions made in the source of both projects I've linked you to.
The short of it is, you need to relate the socket inodes given for each process in /proc/<pid>/fd
to the connections given in /proc/net/<proto>
. Again, example parsing, and how to locate all of these are present in both projects.
Find the PID of a process that uses a port on Windows
Just open a command shell and type (saying your port is 123456):
netstat -a -n -o | find "123456"
You will see everything you need.
The headers are:
Proto Local Address Foreign Address State PID
TCP 0.0.0.0:37 0.0.0.0:0 LISTENING 1111
Identify other end of a unix domain socket connection
Update: It's been possible to to do this using actual interfaces for a while now. Starting with Linux 3.3, the UNIX_DIAG feature provides a netlink-based API for this information, and lsof 4.89 and later support it. See https://unix.stackexchange.com/a/190606/1820 for more information.
Related Topics
How to Boot the Linux Kernel Without Creating an Initrd Image
Find the Process Run by Nohup Command
Why Should I Recompile an Entire Program Just for a Library Update
Option to Display Control Characters in Gedit
How to Catch Duplicate Entries in Text File in Linux
How to Change Port Number for Jenkins Installation in Ubuntu 12.04
How to Pipe Output to a File When Running as a Systemd Service
Find Directories Having Size Greater Than X Mb
How to Diff Top Lines of Two Files Without Intermediate File
Calculate Total Used Disk Space by Files Older Than 180 Days Using Find
Run Command 'At ' 5 Seconds from Now
Match All Files Under All Nested Directories with Shell Globbing
Emacs, Linux and International Keyboard Layouts
Packaging Proprietary Software for Linux