Data Types in the kernel <ldd3 Study Notes>

Source: Internet
Author: User



Data Types in the kernel



Use of Standard C Types


/* * datasize.c -- print the size of common data items * This runs with any Linux kernel (not any Unix, because of <linux/types.h>) * * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet * Copyright (C) 2001 O'Reilly & Associates * * The source code in this file can be freely used, adapted, * and redistributed in source or binary form, so long as an * acknowledgment appears in derived source files.  The citation * should list that the code comes from the book "Linux Device * Drivers" by Alessandro Rubini and Jonathan Corbet, published * by O'Reilly & Associates.   No warranty is attached; * we cannot take responsibility for errors or fitness for use. */#include <stdio.h>#include <sys/utsname.h>#include <linux/types.h>int main(int argc, char **argv){    struct utsname name;    uname(&name); /* never fails :) */    printf("arch   Size:  char  short  int  long   ptr long-long "   " u8 u16 u32 u64\n");    printf(       "%-12s  %3i   %3i   %3i   %3i   %3i   %3i      "   "%3i %3i %3i %3i\n",   name.machine,   (int)sizeof(char), (int)sizeof(short), (int)sizeof(int),   (int)sizeof(long),   (int)sizeof(void *), (int)sizeof(long long), (int)sizeof(__u8),   (int)sizeof(__u16), (int)sizeof(__u32), (int)sizeof(__u64));    return 0;}




Therefore, generic memory addresses in the kernel are usually unsigned long, exploiting the fact that pointers and long integers are always the same size, at least on all the platforms currently supported by Linux.


This is simple. It is interesting to encounter a new struct-struct utsname

After finding it in the kernel for a while, I can't find it all the time. The utsname is a pointer function.

Suddenly <sys/utsname. h> reminded me... This guy user space,

So go to/usr/include/x86... Find in/sys/and find utsname. h.


Paste the entire sys/utsname. h

/* Copyright (C) 1991-2014 Free Software Foundation, Inc.   This file is part of the GNU C Library.   The GNU C Library is free software; you can redistribute it and/or   modify it under the terms of the GNU Lesser General Public   License as published by the Free Software Foundation; either   version 2.1 of the License, or (at your option) any later version.   The GNU C Library is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   Lesser General Public License for more details.   You should have received a copy of the GNU Lesser General Public   License along with the GNU C Library; if not, see   


Haha, write a demo on your own and print them all to satisfy your curiosity.

/*************************************************code writer : EOFcode date : 2014.08.14e-mail:[email protected]code purpose:just a demo for how to use structure--utsnameIf you find something wrong with my code, please touch me by e-mail. Thank you. *************************************************/#include <stdio.h>#include <sys/utsname.h>int main(){struct utsname demo;uname(&demo);printf("sysname: %s\nnodename: %s\nrelease :%s\nmachine: %s\n",demo.sysname,demo.nodename,demo.release,demo.machine);#ifdef __USE_GNUprintf("domainname: %s\n",demo.domainname);#elseprintf("__domainname: %s\n",demo.__domainname);#endifreturn 0;}



Assigning an explicit size to data items



Sometimes kernel code requires data items of a specific size, perhaps to match pre-defined binary structures, to communicate with user space, or to align data within structures by inserting "padding" fields (but refer to the section "Data Alignment" for information about alignment issues ).
 
If a user-space program needs to use these types, it can prefix the names with a double underscore: _ u8 and the other types are defined independent of _ KERNEL __. if, for example, a driver needs to exchange binary structures with a program running in user space by means of ioctl, the header files shoshould declare 32-bit fields in the structures as _ u32.



Time Intervals


When dealing with time intervals, don't assume that there are 1000 jiffies per second. although this is currently true for the i386 architecture, not every LINUX Platform runs at this speed. the assumption can be false even for the x86 if you play with the Hz value (as some people do), and nobody knows what will happen in future
Kernels. whenever you calculate time intervals using jiffies, scale your times using Hz (the number of timer interrupts per second ). for example, to check against a time-out of half a second, compare the elapsed time against Hz/2. more generally, the number of jiffies corresponding to msec milliseconds is always msec x Hz/1000.




Page size

When playing games with memory, remember that a memory page is page_size bytes, not 4 kb. assuming that the page size is 4 kb and hardcoding the value is a common error among PC programmers, instead, supported platforms show page sizes from 4 kb to 64 KB, and sometimes they differ between different implementations of the same platform. the relevant macros are page_size and page_shift. the latter contains the number of bits to shift an address to get its page number.


In fact, in the early 0.1 kernel, Linus was directly used as 4 kb. At that time, he did not expect Linux to be widely used.






Linked lists


To use the list mechanics, your driver must include the file <Linux/list. h>. This file defines a simple structure of Type list_head:

struct list_head {struct list_head *next, *prev;};




List heads must be initialized prior to use with the init_list_head macro. A "Things to do" list head cocould be declared and initialized:

struct list_head todo_list;INIT_LIST_HEAD(&todo_list);


Alternatively, lists can be initialized at compile time:
LIST_HEAD(todo_list);


Several functions are defined in <Linux/list. h> that work with lists:

list_add(struct list_head *new, struct list_head *head);               Adds the new entry immediately after the list head—normally at the beginning of the list. Therefore, it can be used to build stacks. Note, however, that the head need not be the nominal head of the list; if you pass a list_head structure that happens to be in the middle of the list somewhere, the new entry goes immediately after it. Since Linux lists are circular, the head of the list is not generally different from any other entry.


list_add_tail(struct list_head *new, struct list_head *head);              Adds a new entry just before the given list head—at the end of the list, in other words. list_add_tail can, thus, be used to build first-in first-out queues.



list_del(struct list_head *entry);list_del_init(struct list_head *entry);           The given entry is removed from the list. If the entry might ever be reinserted into another list, you should use list_del_init, which reinitializes the linked list pointers.


list_move(struct list_head *entry, struct list_head *head);list_move_tail(struct list_head *entry, struct list_head *head);             The given entry is removed from its current list and added to the beginning of head . To put the entry at the end of the new list, use list_move_tail instead.


list_empty(struct list_head *head);Returns a nonzero value if the given list is empty.



list_splice(struct list_head *list, struct list_head *head);          Joins two lists by inserting list immediately after head . The list_head structures are good for implementing a list of like structures, but the invoking program is usually more interested in the larger structures that make up thelist as a whole. 


A macro, list_entry, is provided that maps a list_head structure pointer back into a pointer to the structure that contains it. It is invoked as follows:


list_entry(struct list_head *ptr, type_of_struct, field_name);           where ptr is a pointer to the struct list_head being used, type_of_struct is the type of the structure containing the ptr , and field_name is the name of the list field within the structure. In our todo_struct structure from before, the list field is called simply list . 


Thus, we wocould turn a list entry into its containing structure with a line such:

struct todo_struct *todo_ptr = list_entry(listptr, struct todo_struct, list);

The list_entry macro takes a little getting used to but is not that hard to use.





"It's like the silence left by the birds"


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.