I'm trying to understand the Linux kernel linked list API.
According to Linux Kernel Linked List I should initialize the list head by INIT_LIST_HEAD but here (Linux Kernel Program) it's suggested to use LIST_HEAD_INIT instead.
Here's a working code I wrote, but I'm not sure if I did it in proper way. Could someone verify that it's OK?
#include <stdio.h>
#include <stdlib.h>
#include "list.h"
typedef struct edge_attr {
int d;
struct list_head list;
} edge_attributes_t;
typedef struct edge {
int id;
edge_attributes_t *attributes;
} edge_t;
int main () {
int i;
struct list_head *pos;
edge_attributes_t *elem;
edge_t *a = (edge_t*)malloc(sizeof(edge_t));
a->id = 12;
a->attributes = (edge_attributes_t*) malloc(sizeof(edge_attributes_t));
INIT_LIST_HEAD(&a->attributes->list);
for (i=0; i<5; ++i) {
elem = (edge_attributes_t*)malloc(sizeof(edge_attributes_t));
elem->d = i;
list_add(&elem->list, &a->attributes->list);
}
list_for_each(pos, &(a->attributes->list)) {
elem = list_entry(pos, edge_attributes_t, list);
printf("%d \n", elem->d);
}
return 0;
}
LIST_HEAD_INIT is a static initializer, INIT_LIST_HEAD is a function. They both initialise a list_head to be empty.
If you are statically declaring a list_head, you should use LIST_HEAD_INIT, eg:
static struct list_head mylist = LIST_HEAD_INIT(mylist);
You should use INIT_LIST_HEAD() for a list head that is dynamically allocated, usually part of another structure. There are many examples in the kernel source.
A quick LXR search shows:
#define LIST_HEAD_INIT(name) { &(name), &(name) }
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
So INIT_LIST_HEAD gets a struct list_head * and initializes it, while LIST_HEAD_INIT returns the address of the passed pointer in a suitable fashioned for use as an initializer for a list:
struct list_head lst1;
/* .... */
INIT_LIST_HEAD(&lst1);
struct list_head lst2 = LIST_HEAD_INIT(lst2);
Related
I am currently learning some Linux Driver writing, and i try to implement list with the Linux Kernel list API.
My code just allocate a list and add 2 elements to it.
All go Ok until i try to free the memory i allocate, here i got a segmentation fault, and from what i test, it come from list_del call.
But i cannot see where i did wrong.
Here is my code :
struct drv_cdev{
int devno;
};
struct drv_dev_itf {
struct drv_cdev cdev; //DATA
struct list_head cdev_list;
};
struct drv_dev {
int number;
struct list_head list_master;
struct drv_dev_itf drv_dev_itf;
};
void add_node(struct drv_dev *dev, int num)
{
struct drv_dev_itf *new_cdev;
new_cdev = kmalloc(sizeof(struct drv_dev_itf*), GFP_KERNEL);
new_cdev->cdev.devno = num;
INIT_LIST_HEAD(&new_cdev->cdev_list);
list_add(&new_cdev->cdev_list, &dev->list_master);
}
void destroy_list(struct drv_dev *dev)
{
struct list_head *position;
struct drv_dev_itf *data_structure;
list_for_each (position, &dev->list_master) {
data_structure = list_entry(position, struct drv_dev_itf, cdev_list);
printk("Devno testing : %d\n", data_structure->cdev.devno);
//dev_node_release(driver_class, &data_structure->cdev);
list_del(position);
printk("List head deleted\n");
/*kfree(data_structure);
printk("List data_structure deleted\n");*/
}
}
static int __init test_init(void)
{
struct drv_dev *dev;
dev = kmalloc(sizeof(*dev), GFP_KERNEL);
INIT_LIST_HEAD(&dev->list_master);
add_node(dev, 1);
add_node(dev, 2);
destroy_list(dev);
kfree(dev);
return 0;
}
Thanks in advance for your answers, have a nice day.
I'm implementing some system calls which are mainly supposed to maintain a list of processes, and a list of open files with each process. However I'm having a hard time debugging the code, which requires recompiling over and over again.
Here are probably my main problems:
When and how can I initialize the list keeping the processes? Currently I'm checking if the list is empty before initializing but it doesn't work. I also tried head == head->prev->next but failed.
What's the correct way to call the list_sort considering the related 'compare' function? I'm getting the error
[ 1827.710802] BUG: unable to handle kernel paging request at fffff550
[ 1827.710808] IP: [] compare+0x8/0x20
[ 1827.710814] *pde = 00a32067 *pte = 00000000
This is the code. I'd really appreciate you reviewing it, especially the init system call whose correct behavior the others rely on.
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/pid.h>
#include <linux/list.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/fdtable.h>
#include <linux/list_sort.h>
#include <linux/slab.h>
struct fileDescriptor {
int fd;
struct list_head list;
};
struct processInfo {
struct task_struct task;
int len_files;
struct fileDescriptor listHead;
struct list_head list;
};
struct processInfo listHead;
int compare(void* priv, struct list_head *a, struct list_head *b)
{
struct processInfo *p1 = container_of(a, struct processInfo, list);
struct processInfo *p2 = container_of(b, struct processInfo, list);
if (p1->task.pid > p2->task.pid) return -1;
else return 1;
}
asmlinkage long sys_init_process_list(pid_t p)
{
struct pid* pid;
struct task_struct *task;
struct files_struct *processFiles;
struct fdtable *filesTable;
struct processInfo *newProcess;
if(list_empty(&listHead.list))
{
printk("____list_empty_____\n");
INIT_LIST_HEAD(&listHead.list);
}
else
printk("____list_not_empty_____\n");
pid = find_get_pid(p);
if (pid == NULL)
{
sys_init_process_list(1);
return 1;
}
else
{
struct list_head *list;
struct task_struct *childTask;
struct fileDescriptor *newfd;
int i = 0;
task = pid_task(pid, PIDTYPE_PID);
newProcess = (struct processInfo*) kmalloc(sizeof(*newProcess), GFP_KERNEL);
//copy task structure
newProcess->task = *task;
//adding file descriptors
INIT_LIST_HEAD(&(newProcess->listHead).list);
processFiles = task->files;
filesTable = files_fdtable(processFiles);
while (filesTable->fd[i] != NULL)
{
newfd = (struct fileDescriptor*) kmalloc(sizeof(*newfd), GFP_KERNEL);
newfd->fd = i;
INIT_LIST_HEAD(&newfd->list);
list_add_tail(&(newfd->list), &(newProcess->listHead).list);
i++;
}
newProcess->len_files = i;
INIT_LIST_HEAD(&newProcess->list);
// add the new node to mylist
list_add_tail(&(newProcess->list), &(listHead.list));
//adding childern
list_for_each(list, &task->children)
{
childTask = list_entry(list, struct task_struct, sibling);
sys_init_process_list(childTask->pid);
}
return 0;
}
}
//////////////////////////////////////////
asmlinkage long sys_sort_process_list(void)
{
if(list_empty(&listHead.list))
{
printk("empty list\n");
return 1;
}
list_sort(NULL, &listHead.list, compare);
return 0;
}
////////////////////////////////////////
asmlinkage long sys_print_process_list(void)
{
struct processInfo *aProcess;
if (sys_sort_process_list())
{
printk("empty list\n");
return 1;
}
list_for_each_entry(aProcess, &listHead.list, list)
{
printk("%d, %d\n", (aProcess->task).pid, aProcess->len_files);
}
return 0;
}
//////////////////////////////////////////////////
asmlinkage long sys_clear_process_list(void)
{
struct processInfo *aProcess, *tmp;
if(list_empty(&listHead.list))
{
printk("empty list\n");
return 1;
}
printk("deleting the list");
list_for_each_entry_safe(aProcess, tmp, &listHead.list, list)
{
printk("freeing %d", (aProcess->task).pid);
list_del(&aProcess->list);
kfree(aProcess);
}
return 0;
}
EDIT: I managed to somehow solve my problem with 'static definition' which is done at compile time, namely I turned
struct processInfo listHead;
to
struct processInfo listHead =
{
.list = LIST_HEAD_INIT(listHead.list)
}
and now everything seems to work just fine. I'm not sure if this is the best way though, so I'm going to keep the question open so other possible solutions may be added.
Unlike to many other object, zero-initialization of linked list leaves it in invalid state. That is, none of linked list's functions can be used for zero-initialized list. Even list_empty one.
Proper initialization of linked list includes LIST_HEAD_INIT (as a struct initializer) or INIT_LIST_HEAD (at runtime).
I'm trying to create a HashTable in C where each 'bucket' is a pointer to a LinkedList. That is, I need to create an array of LinkedList pointers.
As of now, SomeHashTable->Buckets[i] is returning a non-pointer LinkedList. I've been looking for answers everywhere and I just can't find anything. Perhaps I'm overlooking something? I've given my current code below.
HashTable.h
#include "LinkedList.h"
typedef struct HashTable
{
LinkedList* Buckets[1009];
} HashTable;
//Creates new hashtable
HashTable* HashTable_new();
//Hashes and adds a new entry
void HashTable_add(HashTable* Table, int data);
HashTable.c
#include "HashTable.h"
HashTable* HashTable_new()
{
HashTable* newTable = (HashTable*)malloc(sizeof(HashTable));
newTable->Buckets = malloc(1009 * sizeof(LinkedList*));
//Create linked lists
for (int i = 0; i < 1009; i++)
{
newTable->Buckets[i] = LinkedList_new();
}
return newTable;
}
void HashTable_add(HashTable* Table, int data)
{
int index = data % 1009;
//Get bucket to hash to
LinkedList* BucketHead = (Table->Buckets[index]);
//Hash it iiinnnn real good
LinkedList_add_at_end(BucketHead, data);
}
The linked List structs for reference:
typedef struct LinkedListNode {
int data;
struct LinkedListNode *next;
struct LinkedListNode *prev;
} LinkedListNode;
typedef struct LinkedList {
struct LinkedListNode *first;
struct LinkedListNode *last;
} LinkedList;
As H.S.'s comment mentions, there is no need to dynamically --and-- statically allocate the Buckets array.
This line:
newTable->Buckets = malloc(1009 * sizeof(LinkedList*));
is overwriting the pointer to the statically allocated array, which is probably not what you want. For scalability, I would ditch the static array and stick with malloc(). That way you could use an argument to HashTable_new() to specify the size of the buckets array, like so:
HashTable* HashTable_new(int nBuckets)
{
HashTable* newTable = (HashTable*)malloc(sizeof(HashTable));
newTable->Buckets = malloc(nBuckets * sizeof(LinkedList*));
newTable->nBuckets = nBuckets;
//Create linked lists
for (int i = 0; i < nBuckets; i++)
{
newTable->Buckets[i] = LinkedList_new();
}
return newTable;
}
Notice that newTable->Buckets is being allocated as a pointer to a pointer to LinkedList (LinkedList**). You'll need to keep track to the size of Buckets[], so add the variable to the struct as follows:
typedef struct HashTable
{
int nBuckets;
LinkedList **Buckets;
} HashTable;
You should be good as long as LinkedList_new()'s return type is LinkedList*, and don't forget to free() it all when you're done.
I'm trying to create a simple singly linked list in C, and have encountered an infinite "Singal 11 being dropped" loop while running my program in Valgrind.
My .h file:
#ifndef TEST_H
#define TEST_H
struct fruit {
char name[20];
};
struct node {
struct fruit * data;
struct node * next;
};
struct list {
struct node * header;
unsigned count;
};
#endif
My .c file:
#include "test.h"
#include <stdio.h>
#include <string.h>
void init_list(struct list my_list)
{
my_list.header = NULL;
my_list.count = 0;
}
void add_to_list(struct list my_list, struct fruit my_fruit)
{
struct node my_node;
struct node nav_node;
my_node.data = &my_fruit;
my_node.next = NULL;
if(my_list.count == 0) { /* set head node if list is empty */
my_list.header = &my_node;
my_list.count++;
} else {
nav_node = *my_list.header;
while (nav_node.next != NULL) { /* traverse list until end */
nav_node = *nav_node.next;
}
nav_node.next = &my_node;
my_list.count++;
}
}
int main()
{
struct fruit fruit_array[5];
struct list fruit_list;
int i;
strcpy(fruit_array[0].name, "Apple");
strcpy(fruit_array[1].name, "Mango");
strcpy(fruit_array[2].name, "Banana");
strcpy(fruit_array[3].name, "Pear");
strcpy(fruit_array[4].name, "Orange");
init_list(fruit_list);
for(i=0; i < 5; i++) {
add_to_list(fruit_list, fruit_array[i]);
}
return 0;
}
I'm assuming the issue stems from my list traversal in add_to_list, but I'm unsure about what I'm doing wrong.
Thanks!
You're passing structs by value into functions. This will create a copy of the struct in the function, and changes to the copy will not occur on the struct in the calling function.
You should read about pointers in your favorite c-language book.
i have a dynamic number of pointers all having the same size. i need to store all the addresses of my pointers in some place like a link List in order to fetch them later on.
my question is what structs should i use. is the following correct:
struct Node{
int *k;
Node*Next;
}
struct LS{
Node*first,*last;
void push(Node*n);
Node* GetFirst();
Node* GetLast();
}
the LS is the linked list that stores Nodes. and a Node is a struct that holds the address of my pointer and a pointer to the next Node.
am i using int *k to store the address of my pointer correctly? should i continue with this implementation or is there any easier way to do this?
this sample code may help you start...
#include <stdio.h>
struct Node{
int *k;
Node *Next;
}* Temp;
struct LS
{
Node *first,*last;
void push(Node *MyNode)
{
MyNode->Next=NULL;
if(empty())
{
first=MyNode;
last=MyNode;
}
else
{
last->Next = MyNode;
last=MyNode;
}
}
Node* front()
{
return first;
}
void pop()
{
free(first->k);
first=first->Next;
}
bool empty()
{
if(first==NULL) return true;
return false;
}
};
int N=10;
int main()
{
LS Q;Q.first=NULL;
for(int i=0;i<3;i++)
{
Node *NewNode= (Node*)malloc(sizeof(Node));
NewNode->k = (int*)malloc(sizeof(int)*N);
for(int k=0;k<N;k++) NewNode->k[k]=i;
Q.push(NewNode);
}
while(!Q.empty())
{
Temp=Q.front();
for(int i=0;i<N;i++) printf("%d ",Temp->k[i]);
printf("\n");
Q.pop();
}
return 1;
}
Yes, your Node struct is correct.
As to whether there is an easier way it depends. If there is a maximum number of pointers that you will need then an array of pointers would be easier. If you can do it in C++ then an STL vector (can use it like an array, but underneath the hood it can grow dynamically as needed) is easier. If you have to do it in C and it has to be dynamic, though, then no, there is not an easier way.
WDM.H (microsoft header) has a bunch of linked list stuff to look at ( http://msdn.microsoft.com/en-us/library/ff547799(VS.85).aspx ) , I've cut and pasted from that, and added a very simple example.
typedef struct _LIST_ENTRY {
struct _LIST_ENTRY *Flink;
struct _LIST_ENTRY *Blink;
} LIST_ENTRY, *PLIST_ENTRY;
typedef struct _MY_THING
{
LIST_ENTRY ListEntry;
ULONG randomdata1;
ULONG randomdata2;
ULONG randomdata3;
ULONG randomdata4;
} MY_THING, *PMY_THING;
#define CONTAINING_RECORD(address, type, field) ((type *)( \
(PCHAR)(address) - \
(ULONG_PTR)(&((type *)0)->field)))
VOID
InsertHeadList(
IN PLIST_ENTRY ListHead,
IN PLIST_ENTRY Entry
)
{
PLIST_ENTRY Flink;
Flink = ListHead->Flink;
Entry->Flink = Flink;
Entry->Blink = ListHead;
Flink->Blink = Entry;
ListHead->Flink = Entry;
}
VOID
InitializeListHead(
IN PLIST_ENTRY ListHead
)
{
ListHead->Flink = ListHead->Blink = ListHead;
}
PLIST_ENTRY
RemoveHeadList(
IN PLIST_ENTRY ListHead
)
{
PLIST_ENTRY Flink;
PLIST_ENTRY Entry;
Entry = ListHead->Flink;
Flink = Entry->Flink;
ListHead->Flink = Flink;
Flink->Blink = ListHead;
return Entry;
}
void main()
{
LIST_ENTRY HeadOfMyList;
MY_THING Thing;
InitializeListHead(&Head);
// example of add thing to list.
InsertHeadList(&HeadOfMyList, &Thing.ListEntry);
// example of removing thing from the list
PLIST_ENTRY listEntry = RemoveHeadList(&HeadOfMyList);
PMY_THING pThing = (PMY_THING) CONTAINING_RECORD(listEntry, MY_THING, ListEntry);
}