standard c libraries l.
Skip this Video
Loading SlideShow in 5 Seconds..
Standard C Libraries PowerPoint Presentation
Download Presentation
Standard C Libraries

Loading in 2 Seconds...

play fullscreen
1 / 30

Standard C Libraries - PowerPoint PPT Presentation

  • Uploaded on

Standard C Libraries. Application Programmming Interface to System-Calls. Important File-I/O Functions. int open( char *pathname, int flags, … ); int read( int fd, void *buf, size_t count ); int write( int fd, void *buf, size_t count ); int lseek( int fd, loff_t offset, int whence );

I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
Download Presentation

PowerPoint Slideshow about 'Standard C Libraries' - jada

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
standard c libraries

Standard C Libraries

Application Programmming Interface to System-Calls

important file i o functions
Important File-I/O Functions

int open( char *pathname, int flags, … );

int read( int fd, void *buf, size_t count );

int write( int fd, void *buf, size_t count );

int lseek( int fd, loff_t offset, int whence );

int close( int fd );

unix man pages
UNIX ‘man’ pages
  • A convenient online guide to prototypes and semantics of the C linrary functions
  • Example of usage:

$ man 2 open

the open function
The ‘open’ function
  • #include <fcntl.h>
  • int open( char *pathname, int flags, … );
  • Converts a pathname to a file-descriptor
  • File-descriptor is a nonnegative integer
  • Used as a file-ID in subsequent functions
  • ‘flags’ is a symbolic constant:


the close function
The ‘close’ function
  • #include <unistd.h>
  • int close( int fd );
  • Breaks link between file and file-descriptor
  • Returns 0 on success, or -1 if an error
the write function
The ‘write’ function
  • #include <unistd.h>
  • int write( int fd, void *buf, size_t count );
  • Attempts to write up to ‘count’ bytes
  • Bytes are taken from ‘buf’ memory-buffer
  • Returns the number of bytes written
  • Or returns -1 if some error occurred
  • Return-value 0 means no data was written
the read function
The ‘read’ function
  • #include <unistd.h>
  • int read( int fd, void *buf, size_t count );
  • Attempts to read up to ‘count’ bytes
  • Bytes are placed in ‘buf’ memory-buffer
  • Returns the number of bytes read
  • Or returns -1 if some error occurred
  • Return-value 0 means ‘end-of-file’
notes on read and write
Notes on ‘read()’ and ‘write()’
  • These functions have (as a “side-effect”) the advancement of a file-pointer variable
  • They return a negative function-value of -1 if an error occurs, indicating that no actual data could be transferred; otherwise, they return the number of bytes read or written
  • The ‘read()’ function normally does not return 0, unless ‘end-of-file’ is reached
the lseek function
The ‘lseek’ function
  • #include <unistd.h>
  • off_t lseek( int fd, off_t offset, int whence );
  • Modifies the file-pointer variable, based on the value of whence:


  • Returns the new value of the file-pointer (or returns -1 if any error occurred)
getting the size of a file
Getting the size of a file
  • For normal files, your application can find out how many bytes belong to a file using the ‘lseek()’ function:

int filesize = lseek( fd, 0, SEEK_END );

  • But afterward you need to ‘rewind’ the file if you want to read its data:

lseek( fd, 0, SEEK_SET );

what about pseudo files
What about ‘pseudo’ files?
  • You can use standard library functions to open, read, and close a ‘/proc’ pseudo-file
  • You can use ‘lseek’ (except SEEK_END)
  • An example is our ‘howfast.cpp’ program
  • It measures how fast ‘jiffies’ increments
  • It opens, reads, and closes ‘/proc/jiffies’
  • And it also uses ‘lseek’ (to rewind this file)
how these system calls work
How these system-calls work

Operating System


C Runtime Library

Application Program

Module ‘methods’



special device files
Special ‘device’ files
  • UNIX systems treat hardware-devices as special files, so that familiar functions can be used by application programmers to access these devices (open, read, close)
  • But a System Administrator has to create these device-files (in the ‘/dev’ directory)
  • There are two categories of device files: ‘character’ devices, and ‘block’ devices
the mknod command
The ‘mknod’ command
  • To create the device-node for a character device, an Administrator executes ‘mknod’

root# mknod /dev/scull c 48 0

  • Here ‘/dev/scull’ is the file’s pathname, ‘c’ indicates that it’s a character-mode device, 48 is its (unique) ‘major’ ID-number, and 0 is its (unique) ‘minor’ ID-number
  • Default access-privileges: r w - r - - r - -
  • Can be modified using ‘chmod’ command
what s new in 2 6
What’s new in 2.6?
  • Earlier Linux kernels stored the ‘/dev’ files on the hard disk (so they were persistent)
  • The 2.6 kernel stores them in a ram-disk
  • So they ‘disappear’ during every shutdown
  • You need ‘root’ privileges to re-build them!
  • (Fortunately this step can be automated if device-nodes are in ‘/etc/udev/devices’ )
a useful device driver
A useful device-driver
  • We can create a character-mode driver for the processor’s physical memory (i.e. ram)
  • (Our machines have 1-GB of physical ram)
  • But another device-file is named ‘/dev/ram’ so ours will be: ‘/dev/dram’ (dynamic ram)
  • We’ve picked 253 as its ‘major’ ID-number
  • Our SysAdmin setup a device-node using: root# mknod /dev/dram c 253 0
device knowledge
Device knowledge
  • Before you can write a device-driver, you must understand how the hardware works
  • Usually this means you need to obtain the programmer manual (from manufacturer)
  • Nowdays this can often be an obstacle
  • But some equipment is standardized, or is well understood (because of its simplicity)
1 gb ram has zones
1-GB RAM has ‘zones’





(= 1GB)



legacy dma
Legacy DMA
  • Various older devices rely on the PC/AT’s DMA controller to perform data-transfers
  • This chip could only use 24-bit addresses
  • Only the lowest 16-megabytes of physical memory are ‘visible’ to these devices:

224 = 0x01000000 (16-megabytes)

  • Linux tries to conserve its use of memory from this ZONE_LOW region for anything except DMA (so it will available if needed)
high memory
‘HIGH’ memory
  • Linux traditionally tried to ‘map’ as much physical memory as possible into virtual addresses allocated to the kernel-space
  • Before the days when systems had 1-GB or more of installed memory, Linux could linearly map ALL of the physical memory into the 1-GB kernel-region:

0xC0000000 – 0xFFFFFFFF

  • But with 1GB there’s not enough room!
the 896 mb limit
The 896-MB limit





User space


Kernel space



linearly mapped

Physical address-space

A special pair of kernel-functions

named ‘kmap()’ and ‘kunmap()’

can be called by device-drivers to

temporarily map pages of physical

memory into ‘vacant’ areas within

the kernel’s virtual address-space

Virtual address-space

copy to user
  • With kernel 2.6, it is possible to configure the user-space versus kernel-space ‘split’ so that nearly 4GB of physical memory is always linearly mapped into kernel-space
  • The configuration-option is CONFIG_4GB
  • With this option enabled, the user-space and kernel-space use two different maps
  • So device-drivers need a special function to transfer kernel-data to a user’s buffer
driver module structure
Driver-module structure
  • We will need three kernel header-files:
    • #include <linux/module>

// for printk(), register_chrdev(), unregister_chrdev()

    • #include <linux/highmem.h>

// for kmap(), kunmap(), and ‘num_physpages’

    • #include <asm/uaccess.h>

// for copy_to_user()

our dram size global
Our ‘dram_size’ global
  • Our ‘init_module()’ function will compute the size of the installed physical memory
  • It will be stored in a global variable, so it can be accessed by our driver ‘methods’
  • It is computed from a kernel global using the PAGE_SIZE constant (=4096 for x86)

dram_size = num_physpages * PAGE_SIZE

major id number
‘major’ ID-number
  • Our ‘major’ device ID-number is needed when we ‘register’ our device-driver with the kernel (during initialization) and later when we ‘unregister’ our device-driver (during the cleanup procedure):

int my_major = 253; // static ID-assignment

our file operations
Our ‘file_operations’
  • Our ‘dram’ device-driver does not need to implement special ‘methods’ for doing the ‘open()’, ‘write()’, or ‘release()’ operations (the kernel ‘default’ operations will suffice)
  • But we DO need to implement ‘read()’ and ‘llseek()’ methods
  • Our ‘llseek()’ code here is very standard
  • But ‘read()’ is specially crafted for DRAM
using our driver
Using our driver
  • We have provided a development tool on the class website (named ‘fileview.cpp’) which can be used to display the contents of files (including device-files)
  • The data is shown in hex and ascii formats
  • The arrow-keys can be used for navigation
  • The enter-key allows an offset to be typed
  • Keys ‘b’, ‘w’, ‘d’ and ‘q’ adjust data-widths
in class exercise 1
In-class exercise #1
  • Install the ‘dram.ko’ device-driver module; then use ‘fileview’ to browse the contents of the processor’s physical memory:

$ fileview /dev/dram

control register cr3
Control Register CR3
  • Register CR3 holds the physical-address of the system’s current ‘page-directory’
  • The page-directory is an array of 1024 entries, showing how ‘virtual addresses’ are currently ‘mapped’ to physical pages
  • With ‘fileview’ you can find and examine this important kernel data-structure – but you must know the value in register CR3
in class exercise 2
In-class exercise #2
  • Use the ‘newinfo’ wizard to quickly create a pseudo-file (named ‘/proc/cr3’) that will allow user-programs to obtain the current value of the Pentium’s CR3 register
  • Write a tool (named ‘seepgdir.cpp’) that will read ‘/proc/cr3’ to get the address of the page-directory, then read it from the ‘/dev/dram’ device and print it onscreen