Using Kernel Services
Feb 1, 2002
Yongguang Zhang
Today's Lecture
- Q&A
- /proc file system
- Project 3 Handout
Q&A
- How is project 2?
- Too easy?
- Too hard?
- Have enough time to finish it?
/proc File System
- Pseudo-filesystem as an interface to kernel data structures
- Each file correspond to a data structure in kernel
- A way for data transfer between kernel/user space
- What is the general way we just learned last time?
- What is limitation of the general way?
- Purpose of /proc filesystem: an extensible mechanism to support all types of data transfer in a common interface
- Most files in /proc are read-only, some allow kernel variables to be changed.
"The general way"
- System call with memory copy
- Add a new system call
- Call get_user() and put_user()
- Limitation
- Not scalable: each type of data transfer needs a new system call
- Not extensible: system call interfaces and data structures vary a lot
Numerical Subdirectory
- Kernel data structures for the running processes
- One subdirectory per process
- Named by process ID
- Example files:
- cmdline the complete command line for the process.
- cpu CPU usage by this process
- cwd symbolic link to the $CWD of the process.
- environ contains the environment for the process.
- exe symbolic link to the running binary.
- fd/ a subdirectory of open files by the process.
- ...
Non-Numerical Files/Directories
cpuinfo information about the CPUs
...
net/ many files/subdir for many parts of Linux networking
net/arp
net/dev
net/route
...
sys/ sysctl files (dynamic configurable kernel parameters)
...
Too many of them!
Read/Write from User Space
- Just like a normal file
- Examples:
- To read in shell:
- To write in shell:
echo cool-name > /proc/sys/kernel/hostname
- For configurable kernel parameters (/proc/sys/)
- Also with sysctl command (read/write)
/sbin/sysctl -w kernel/hostname= "cool-name"
Creating New /proc File in Kernel
- Understand the struct proc_dir_entry data object
- Write callback functions
- Create struct proc_dir_entry data object
/proc File Data Object
struct proc_dir_entry {
unsigned short low_ino;
unsigned short namelen;
const char *name;
mode_t mode;
nlink_t nlink;
uid_t uid;
gid_t gid;
unsigned long size;
struct inode_operations * proc_iops;
struct file_operations * proc_fops;
get_info_t *get_info;
struct module *owner;
struct proc_dir_entry *next, *parent, *subdir;
void *data;
read_proc_t *read_proc;
write_proc_t *write_proc;
atomic_t count; /* use count */
int deleted; /* delete flag */
kdev_t rdev;
};
Callbacks
Communication with User Space
- User space to read data from kernel
- User Space: to make read() system call
- Kernel: will call the corresponding e.read_proc()
sys_read() => ... => e.read_proc()
- User space to write data to kernel
- User Space: to make write() system call
- Kernel: will call the corresponding e.write_proc()
sys_write() => ... => e.write_proc()
- Q: how/where is the transfer of data/control really taken place?
Adding Entries to /proc File System
- To add “regular” file:
struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, struct proc_dir_entry *parent);
- To make symbolic link:
struct proc_dir_entry *proc_symlink(const char *, struct proc_dir_entry *, const char *);
- To create sysctl file
- To make subdirectory
Summary
- Steps
- Writing callback functions
- Create /proc files by calling proc_fs routines
- Use /proc inside kernel modules
- Subtle difference (see example)
- Documentation and example:
- Under linux kernel source tree:
- Documentation/DocBook/procfs_example.c
Providing System Services
- Implementing as a system call
- Avoid if possible
- But as a student you should know how it works
- Implementing as a /proc file system
- Implementing as ioctl()
Steps for Adding New System Calls
- Add a wrapper function in user-space code
- Include <linux/unistd.h>
- Use _syscall0() ... _syscall5()
- Include a macro definition for __NR_XYZ
- In include/asm-i386/unistd.h
- Write the corresponding service routine in kernel source tree
(e.g., sys_XYZ())
- In arch/i386/kernel/entry.S
- Add an entry to system call dispatch table
- Update total syscall number: .rept NR_syscalls-222
For Other Architecture
- Previous steps are for I386 architecture
- include/asm-i386/unistd.h
- arch/i386/kernel/entry.S
- Need additional steps for "UM" architecture
- Need extra changes if you are to support other architectures
- include/asm-XXX/unistd.h
- arch/XXX/kernel/entry.S
Adding System Calls in UML
- In addition to making changes to i386 architecture ...
- In arch/um/kernel/sys_call_table.c
- Add it to the list of externs as
extern syscall_handler_t sys_XYZ;
- Add it to the call table (sys_call_table[]) as
- If it is the last system call,
- In arch/um/include/sysdep-i386/syscalls.h,
#define LAST_SYSCALL __NR_XYZ
- In arch/um/include/sysdep/syscalls.h, add
#define LAST_SYSCALL __NR_XYZ
Homework
- Try out the /proc file system example
- You may have already done that in Project 2
- Think about Project 3
- Implementing a system call
- Exercise 5: Kernel Projects in Linux
- Due next Friday, 11:59pm
© 2002 Yongguang Zhang