another device-driver?

27
Another device-driver? Getting ready to program the network interface

Upload: angus

Post on 14-Jan-2016

46 views

Category:

Documents


0 download

DESCRIPTION

Another device-driver?. Getting ready to program the network interface. Inexpensive NIC: $8.95. RealTek 8139 processor. ConnectGear D30-TX (Made in China). Hardware components. main memory. packet. nic. TX FIFO. transceiver. buffer. LAN cable. B U S. RX FIFO. CPU. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Another device-driver?

Another device-driver?

Getting ready to program the network interface

Page 2: Another device-driver?

Inexpensive NIC: $8.95

ConnectGear D30-TX (Made in China)

RealTek 8139 processor

Page 3: Another device-driver?

nic

Hardware components

TX FIFO

RX FIFO

transceiver LANcableB

US

main memory

packet

buffer

CPU

Page 4: Another device-driver?

PC-to-PC connection

PC

NIC

PC

NIC

UTP Category-5“crossover” cable

RJ-45connector

RJ-45connector

Page 5: Another device-driver?

Kudlick Classroom’s stations

8 9 10 15 16 17 18 19 20 28 29 30

4 5 6 7 11 12 13 14 24 25 26 27

1 2 3 21 22 23

LECTERN

Page 6: Another device-driver?

In-class exercise #1

• A network device-driver will need to know certain identifying information about the workstation it is running on -- so it can let other stations know to whom they should send their reply-messages

• Our ‘utsinfo.c’ module shows how kernel code can find out the name of the ‘node’ on which it is executing

• Try it out – then study its code to use later

Page 7: Another device-driver?

Some NIC characteristics

• With our previous device-driver examples (e.g., dram, vram, and hd), the data to be read was already there waiting to be read

• But with a network interface card (NIC), we may want to read its data before any data has arrived from other workstations

• In such cases we would like to wait until data arrives rather than abandon reading

Page 8: Another device-driver?

Could do ‘busy waiting’?

• It is possible for a network driver to ‘poll’ a status-bit continuously until data is ready (as we did with the IDE Controller’s status)

• This is called ‘busy waiting’ – it could take up a lot of valuable time before any benefit is realized

• In a multitasking system we want to avoid ‘busy waiting’ whenever possible!

Page 9: Another device-driver?

Alternative is ‘blocking’

• If trying to read from device-files when no data is present, but new data is expected to arrive, the system can ‘block’ the task from consuming valuable CPU time while it waits, by ‘putting the task to sleep’ and arranging for it to be ‘awakened’ as soon as some new data has actually arrived

Page 10: Another device-driver?

What does ‘sleep’ mean?

• The Linux kernel puts a task to sleep by simply modifying the value of its ‘state’ variable:– TASK_RUNNING– TASK_STOPPED– TASK_UNINTERRUPTIBLE– TASK_INTERRUPTIBLE

• Only tasks with ‘state == TASK_RUNNING’ are scheduled to be granted time on the CPU

Page 11: Another device-driver?

What does ‘wakeup’ mean?

• A sleeping task is one whose ‘task.state’ is equal to ‘TASK_INTERRUPTIBLE’ or to ‘TASK_UNINTERRUPTIBLE’

• A sleeping task is ‘woken up’ by changing its ‘task,state’ to be ‘TASK_RUNNING’

• When the Linux scheduler sees that a task is in the ‘TASK_RUNNING’ state, it grants that task some CPU time for execution

Page 12: Another device-driver?

‘run’ queues and ‘wait’ queues

• In order for Linux to efficiently manage the scheduling of the various tasks, separate queues are maintained for ‘running’ tasks and for tasks that are asleep while waiting for a particular event to occur (such as the arrival of new data from the network)

Page 13: Another device-driver?

Some tasks are ‘ready-to-run’

Page 14: Another device-driver?

Kernel support-routines

• The Linux kernel makes it easy for drivers to perform the ‘sleep’ and ‘wakeup’ actions while avoiding potential ‘race conditions’ which are inherent in a ‘preemptive’ kernel that might be running on multiple CPUs

Page 15: Another device-driver?

Use of Linux wait-queues

• #include <linux/sched.h>

• wait_queue_head_t my_queue;

• init_waitqueue_head( &my_queue );

• sleep_on( &my_queue );

• wake_up( &my_queue );

• But can’t unload driver if task stays asleep!

Page 16: Another device-driver?

Kernel waitqueues

waitqueue

waitqueue

waitqueue

waitqueue

Page 17: Another device-driver?

‘interruptible’ is preferred

#include <linux/sched.h>

wait_queue_head_t wq;

init_waitqueue_head( &wq );

wait_event_interruptible( wq, <condition> );

wake_up_interruptible( &wq );

An ‘interruptible’ sleep can awoken by a signal --

-- in case you might want to ‘unload’ your driver!

Page 18: Another device-driver?

A convenient ‘macro’

• DECLARE_WAIT_QUEUE_HEAD( wq );

• This statement can be placed outside yourmodule’s functions (i.e., a ‘global’ object)

• It combines declaration with initialization:wait_queue_head_t wq;init_waitqueue_head( &wq );

Page 19: Another device-driver?

A character device: ‘stash’

• Device works like a public ‘clipboard’

• It uses kernel memory to store its data

• It allows ‘communication’ between tasks

• What one task writes, another can read!

Page 20: Another device-driver?

Ringbuffer

• A first-in first-out data-structure (FIFO)

• Uses a storage array of finite length

• Uses two array-indices: ‘head’ and ‘tail’

• Data is added at the current ‘tail’ position

• Data is removed from the ‘head’ position

Page 21: Another device-driver?

Ringbuffer (continued)

• One array-position is always left unused

• Condition ‘head == tail’ means “empty”

• Condition tail == head-1 means “full”

• Both ‘head’ and ‘tail’ will “wraparound”

• Calculation: next = ( next+1 )%RINGSIZE;

Page 22: Another device-driver?

read-algorithm for ‘stash’

• if ( ringbuffer_is_empty )

{

// sleep, until another task supplies some data

// or else exit if a signal is received by this task

}

• Remove a byte from the ringbuffer; • Copy the byte to user-space;• Awaken any sleeping writers;• return 1;

Page 23: Another device-driver?

write-algorithm for ‘stash’

• if ( ringbuffer_is_full )

{

// sleep, until some data is removed by another task

// or else exit if a signal is received by this task

}

• Copy a byte from user-space;• Insert this byte into ringbuffer;• Awaken any sleeping readers;• return 1;

Page 24: Another device-driver?

Demonstration of ‘stash’

• Quick demo: we can use I/O redirection

• For demonstrating ‘write’ to /dev/stash:

$ echo “Hello” > /dev/stash

• For demonstrating ‘read’ from /dev/stash:

$ cat /dev/stash

Page 25: Another device-driver?

The ‘device’ file-node

• We cannot use the ‘stash.c’ device-driver until a device-node has been created that allows both ‘read’ and ‘write’ access (the SysAdmin must do this setup for us):

#root mknod /dev/stash c 40 0

#root chmod a+rw /dev/stash

• You can try using the ‘sudo’ command to these steps (if that privilege was granted)

Page 26: Another device-driver?

Alternative: use ‘/dev/foo’

• If you cannot create the ‘/dev/stash’ node, you can use an existing ‘generic’ node if you change the driver’s ‘major’ number and the device-name you register it with

• Use the command: $ ls –l /dev/foo to find out what major number you must use

Page 27: Another device-driver?

In-class exercise #2

• Add a ‘get_info()’ function to this driver to create a pseudo-file (named ‘/proc/stash’) that will show the current contents of the ringbuffer (if any) and the current values for the ‘head’ and ‘tail’ buffer-indices

• Don’t forget: use ‘create_proc_info_entry()’ in your ‘init_module()’ function, and call ‘remove_proc_entry()’ during ‘cleanup’