linux/kernel/module development: Difference between revisions

From Free Pascal wiki
Jump to navigationJump to search
No edit summary
No edit summary
Line 15: Line 15:
It is obvious that when programming Linux kernel modules, one can not use the standard FPC RTL. As nos ''standard kernel RTL'' is provided, you have to write your own one. This is not very easy. A good start point could be the following
It is obvious that when programming Linux kernel modules, one can not use the standard FPC RTL. As nos ''standard kernel RTL'' is provided, you have to write your own one. This is not very easy. A good start point could be the following
<code>
<code>
unit system;
unit system;
{$TYPEINFO OFF}
{$TYPEINFO OFF}
interface
interface
{Paѕcal common type aliases}
{Paѕcal common type aliases}
type
type
{Basic embedded types}
{Basic embedded types}
u8 = Byte;
u8 = Byte;
u16 = Word;
u16 = Word;
u32 = LongWord;
u32 = LongWord;
u64 = QWord;
u64 = QWord;
s8 = ShortInt;
s8 = ShortInt;
s16 = SmallInt;
s16 = SmallInt;
s32 = LongInt;
s32 = LongInt;
s64 = Int64;
s64 = Int64;
{Integer types}
{Integer types}
DWord = LongWord;
DWord = LongWord;
Cardinal = LongWord;
Cardinal = LongWord;
Integer = SmallInt;
Integer = SmallInt;
UInt64 = QWord;
UInt64 = QWord;
{$ifdef CPU64}
{$ifdef CPU64}
SizeInt = Int64;
SizeInt = Int64;
SizeUInt = QWord;
SizeUInt = QWord;
PtrInt = Int64;
PtrInt = Int64;
PtrUInt = QWord;
PtrUInt = QWord;
ValSInt = int64;
ValSInt = int64;
ValUInt = qword;
ValUInt = qword;
{$endif CPU64}
{$endif CPU64}
{$ifdef CPU32}
{$ifdef CPU32}
SizeInt = Longint;
SizeInt = Longint;
SizeUInt = DWord;
SizeUInt = DWord;
PtrInt = Longint;
PtrInt = Longint;
PtrUInt = DWord;
PtrUInt = DWord;
ValSInt = Longint;
ValSInt = Longint;
ValUInt = Cardinal;
ValUInt = Cardinal;
{$endif CPU32}
{$endif CPU32}
{Zero - terminated strings }
{Zero - terminated strings }
PChar = ^Char;
PChar = ^Char;
PPChar = ^PChar;
PPChar = ^PChar;
{Pointers}
{Pointers}
PSmallInt = ^Smallint;
PSmallInt = ^Smallint;
PShortInt = ^Shortint;
PShortInt = ^Shortint;
PInteger  = ^Integer;
PInteger  = ^Integer;
PByte    = ^Byte;
PByte    = ^Byte;
PWord    = ^word;
PWord    = ^word;
PDWord    = ^DWord;
PDWord    = ^DWord;
PLongWord = ^LongWord;
PLongWord = ^LongWord;
PLongint  = ^Longint;
PLongint  = ^Longint;
PCardinal = ^Cardinal;
PCardinal = ^Cardinal;
PQWord    = ^QWord;
PQWord    = ^QWord;
PInt64    = ^Int64;
PInt64    = ^Int64;
PPtrInt  = ^PtrInt;
PPtrInt  = ^PtrInt;
PPtrUInt  = ^PtrUInt;
PPtrUInt  = ^PtrUInt;
PSizeInt  = ^SizeInt;
PSizeInt  = ^SizeInt;
PPointer  = ^Pointer;
PPointer  = ^Pointer;
PPPointer = ^PPointer;
PPPointer = ^PPointer;
PBoolean  = ^Boolean;
PBoolean  = ^Boolean;
PWordBool = ^WordBool;
PWordBool = ^WordBool;
PLongBool = ^LongBool;
PLongBool = ^LongBool;
{Other types}
{Other types}
HRESULT = type Longint;
HRESULT = type Longint;
TDateTime = type Double;
TDateTime = type Double;
TError = type Longint;
TError = type Longint;
const
const
KERN_INFO='KERNEL:INFO:';
KERN_INFO='KERNEL:INFO:';
KERN_ALERT='KERNEL:ALERT:';
KERN_ALERT='KERNEL:ALERT:';
DEVICE_NAME='kpmod';
DEVICE_NAME='kpmod';
PROCFS_MAX_SIZE=1024;
EPERM = 1;{Operation not permitted}
PROCFS_NAME='kpmod';
ENOENT = 2;{No such file or directory}
EPERM = 1;{Operation not permitted}
ESRCH = 3;{No such process}
ENOENT = 2;{No such file or directory}
EINTR = 4;{Interrupted system call}
ESRCH = 3;{No such process}
EIO = 5;{I/O error}
EINTR = 4;{Interrupted system call}
ENXIO = 6;{No such device or address}
EIO = 5;{I/O error}
E2BIG = 7;{Argument list too long}
ENXIO = 6;{No such device or address}
ENOEXEC = 8;{Exec format error}
E2BIG = 7;{Argument list too long}
EBADF = 9;{Bad file number}
ENOEXEC = 8;{Exec format error}
ECHILD = 10;{No child processes}
EBADF = 9;{Bad file number}
EAGAIN = 11;{Try again}
ECHILD = 10;{No child processes}
ENOMEM = 12;{Out of memory}
EAGAIN = 11;{Try again}
EACCES = 13;{Permission denied}
ENOMEM = 12;{Out of memory}
EFAULT = 14;{Bad address}
EACCES = 13;{Permission denied}
ENOTBLK = 15;{Block device required}
EFAULT = 14;{Bad address}
EBUSY = 16;{Device or resource busy}
ENOTBLK = 15;{Block device required}
EEXIST = 17;{File exists}
EBUSY = 16;{Device or resource busy}
EXDEV = 18;{Cross-device link}
EEXIST = 17;{File exists}
ENODEV = 19;{No such device}
EXDEV = 18;{Cross-device link}
ENOTDIR = 20;{Not a directory}
ENODEV = 19;{No such device}
EISDIR = 21;{Is a directory}
ENOTDIR = 20;{Not a directory}
EINVAL = 22;{Invalid argument}
EISDIR = 21;{Is a directory}
ENFILE = 23;{File table overflow}
EINVAL = 22;{Invalid argument}
EMFILE = 24;{Too many open files}
ENFILE = 23;{File table overflow}
ENOTTY = 25;{Not a typewriter}
EMFILE = 24;{Too many open files}
ETXTBSY = 26;{Text file busy}
ENOTTY = 25;{Not a typewriter}
EFBIG = 27;{File too large}
ETXTBSY = 26;{Text file busy}
ENOSPC = 28;{No space left on device}
EFBIG = 27;{File too large}
ESPIPE = 29;{Illegal seek}
ENOSPC = 28;{No space left on device}
EROFS = 30;{Read-only file system}
ESPIPE = 29;{Illegal seek}
  EMLINK = 31;{Too many links}
EROFS = 30;{Read-only file system}
EPIPE = 32;{Broken pipe}
EMLINK = 31;{Too many links}
EDOM = 33;{Math argument out of domain of func}
EPIPE = 32;{Broken pipe}
ERANGE = 34;{Math result not representable}
EDOM = 33;{Math argument out of domain of func}
type
ERANGE = 34;{Math result not representable}
{Kernel types}
type
mode_t = Word;
{Kernel types}
nlink_t = DWord;
mode_t = Word;
uid_t = Word;
nlink_t = DWord;
fl_owner_t = ^files_struct;
uid_t = Word;
  gid_t = Word;
fl_owner_t = ^files_struct;
off_t = LongInt;
gid_t = Word;
loff_t = Int64;
off_t = LongInt;
loff_t = Int64;
Ploff_t = ^loff_t;
Ploff_t = ^loff_t;
size_t = DWord;
size_t = DWord;
ssize_t = LongInt;
ssize_t = LongInt;
{$PACKRECORDS C}
{$PACKRECORDS C}
atomic_t = record
atomic_t = record
counter:LongInt;
counter:LongInt;
end;
end;
files_struct = record
files_struct = record
  {read mostly part}
  {read mostly part}
count:atomic_t;
count:atomic_t;
//struct fdtable *fdt;
//struct fdtable *fdt;
//struct fdtable fdtab;
//struct fdtable fdtab;
  {written part on a separate cache line in SMP}
  {written part on a separate cache line in SMP}
//spinlock_t file_lock ____cacheline_aligned_in_smp;
//spinlock_t file_lock ____cacheline_aligned_in_smp;
//int next_fd;
//int next_fd;
//struct embedded_fd_set close_on_exec_init;
//struct embedded_fd_set close_on_exec_init;
//struct embedded_fd_set open_fds_init;
//struct embedded_fd_set open_fds_init;
//struct file * fd_array[NR_OPEN_DEFAULT];
//struct file * fd_array[NR_OPEN_DEFAULT];
end;
  end;
filldir_t = function(arg1:Pointer; arg2:PChar; arg3:LongInt; arg4:loff_t; arg5:u64; arg6:DWord):LongInt; cdecl;
filldir_t = function(arg1:Pointer; arg2:PChar; arg3:LongInt; arg4:loff_t; arg5:u64; arg6:DWord):LongInt; cdecl;
read_actor_t = function(arg1:Pointer{read_descriptor_t *}; arg2:Pointer{struct page *}; arg3:DWord; arg4:DWord):LongInt; cdecl;
read_actor_t = function(arg1:Pointer{read_descriptor_t *}; arg2:Pointer{struct page *}; arg3:DWord; arg4:DWord):LongInt; cdecl;
Pfile_operations = ^file_operations;
Pfile_operations = ^file_operations;
file_operations = record
file_operations = record
owner:Pointer;{struct module *}
owner:Pointer;{struct module *}
llseek:function(filp:Pointer{struct file *}; offset:loff_t; whence:LongInt):loff_t; cdecl;
llseek:function(filp:Pointer{struct file *}; offset:loff_t; whence:LongInt):loff_t; cdecl;
read:function(filp:Pointer{struct file *}; buf:PChar; count:size_t; offset:Ploff_t):ssize_t; cdecl;
read:function(filp:Pointer{struct file *}; buf:PChar; count:size_t; offset:Ploff_t):ssize_t; cdecl;
write:function(filp:Pointer{struct file *}; buf:PChar; count:size_t; offset:Ploff_t):ssize_t; cdecl;
write:function(filp:Pointer{struct file *}; buf:PChar; count:size_t; offset:Ploff_t):ssize_t; cdecl;
aio_read:function(kiocb:Pointer{struct kiocb *}; iovec:Pointer{const struct iovec *}; count:DWord; offset:loff_t):ssize_t; cdecl;
aio_read:function(kiocb:Pointer{struct kiocb *}; iovec:Pointer{const struct iovec *}; count:DWord; offset:loff_t):ssize_t; cdecl;
aio_write:function(kiocb:Pointer{struct kiocb *}; iovec:Pointer{const struct iovec *}; count:DWord; offset:loff_t):ssize_t; cdecl;
aio_write:function(kiocb:Pointer{struct kiocb *}; iovec:Pointer{const struct iovec *}; count:DWord; offset:loff_t):ssize_t; cdecl;
readdir:function(filp:Pointer{struct file *}; buf:Pointer; filldir:filldir_t):LongInt; cdecl;
readdir:function(filp:Pointer{struct file *}; buf:Pointer; filldir:filldir_t):LongInt; cdecl;
poll:function(filp:Pointer{struct file *}; poll_table:Pointer{struct poll_table_struct *}):DWord; cdecl;
poll:function(filp:Pointer{struct file *}; poll_table:Pointer{struct poll_table_struct *}):DWord; cdecl;
ioctl:function(inode:Pointer{struct inode *}; filp:Pointer{struct file *}; arg1:DWord; arg2:DWord):LongInt; cdecl;
ioctl:function(inode:Pointer{struct inode *}; filp:Pointer{struct file *}; arg1:DWord; arg2:DWord):LongInt; cdecl;
unlocked_ioctl:function(filp:Pointer{struct file *}; arg1:DWord; arg2:DWord):LongInt; cdecl;
unlocked_ioctl:function(filp:Pointer{struct file *}; arg1:DWord; arg2:DWord):LongInt; cdecl;
compat_ioctl:function(filp:Pointer{struct file *}; arg1:DWord; arg2:DWord):LongInt; cdecl;
compat_ioctl:function(filp:Pointer{struct file *}; arg1:DWord; arg2:DWord):LongInt; cdecl;
mmap:function(filp:Pointer{struct file *}; vm_area_struct:Pointer{ struct vm_area_struct *}):LongInt; cdecl;
mmap:function(filp:Pointer{struct file *}; vm_area_struct:Pointer{ struct vm_area_struct *}):LongInt; cdecl;
open:function(inode:Pointer{struct inode *}; filp:Pointer{struct file *}):LongInt; cdecl;
open:function(inode:Pointer{struct inode *}; filp:Pointer{struct file *}):LongInt; cdecl;
flush:function(filp:Pointer{struct file *}; id:fl_owner_t):LongInt; cdecl;
flush:function(filp:Pointer{struct file *}; id:fl_owner_t):LongInt; cdecl;
release:function(inode:Pointer{struct inode *}; filp:Pointer{struct file *}):LongInt; cdecl;
release:function(inode:Pointer{struct inode *}; filp:Pointer{struct file *}):LongInt; cdecl;
fsync:function(filp:Pointer{struct file *}; arg1:Pointer{ struct dentry *}; datasync:LongInt):LongInt; cdecl;
fsync:function(filp:Pointer{struct file *}; arg1:Pointer{ struct dentry *}; datasync:LongInt):LongInt; cdecl;
aio_fsync:function(kiocb:Pointer{struct kiocb *}; datasync:LongInt):LongInt; cdecl;
aio_fsync:function(kiocb:Pointer{struct kiocb *}; datasync:LongInt):LongInt; cdecl;
fasync:function(arg1:LongInt; filp:Pointer{struct file *}; arg2:LongInt):LongInt; cdecl;
fasync:function(arg1:LongInt; filp:Pointer{struct file *}; arg2:LongInt):LongInt; cdecl;
lock:function(filp:Pointer{struct file *}; arg1:LongInt; arg2:Pointer{ struct file_lock *}):LongInt; cdecl;
lock:function(filp:Pointer{struct file *}; arg1:LongInt; arg2:Pointer{ struct file_lock *}):LongInt; cdecl;
sendfile:function(filp:Pointer{struct file *}; arg1:Pointer{ loff_t *}; arg2:size_t; arg3:read_actor_t; arg4:Pointer{ void *}):ssize_t; cdecl;
sendfile:function(filp:Pointer{struct file *}; arg1:Pointer{ loff_t *}; arg2:size_t; arg3:read_actor_t; arg4:Pointer{ void *}):ssize_t; cdecl;
sendpage:function(filp:Pointer{struct file *}; arg1:Pointer{ struct page *}; arg2:LongInt; arg3:size_t; arg4:Pointer{ loff_t *}; arg5:LongInt):ssize_t; cdecl;
sendpage:function(filp:Pointer{struct file *}; arg1:Pointer{ struct page *}; arg2:LongInt; arg3:size_t; arg4:Pointer{ loff_t *}; arg5:LongInt):ssize_t; cdecl;
get_unmapped_area:function(filp:Pointer{struct file *}; arg1:DWord; arg2:DWord; arg3:DWord; arg4:DWord):DWord; cdecl;
get_unmapped_area:function(filp:Pointer{struct file *}; arg1:DWord; arg2:DWord; arg3:DWord; arg4:DWord):DWord; cdecl;
check_flags:function(falgs:LongInt):LongInt; cdecl;
check_flags:function(falgs:LongInt):LongInt; cdecl;
dir_notify:function(filp:Pointer{struct file *}; arg:DWord):LongInt; cdecl;
dir_notify:function(filp:Pointer{struct file *}; arg:DWord):LongInt; cdecl;
flock:function(filp:Pointer{struct file *}; arg1:LongInt; arg2:Pointer{ struct file_lock *}):LongInt; cdecl;
flock:function(filp:Pointer{struct file *}; arg1:LongInt; arg2:Pointer{ struct file_lock *}):LongInt; cdecl;
splice_write:function(arg1:Pointer{struct pipe_inode_info *}; filp:Pointer{struct file *}; arg2:Pointer{ loff_t *}; arg3:size_t; arg4:DWord):ssize_t; cdecl;
splice_write:function(arg1:Pointer{struct pipe_inode_info *}; filp:Pointer{struct file *}; arg2:Pointer{ loff_t *}; arg3:size_t; arg4:DWord):ssize_t; cdecl;
splice_read:function(filp:Pointer{struct file *}; arg1:Pointer{ loff_t *}; arg2:Pointer{ struct pipe_inode_info *}; arg3:size_t; arg4:DWord):ssize_t; cdecl;
splice_read:function(filp:Pointer{struct file *}; arg1:Pointer{ loff_t *}; arg2:Pointer{ struct pipe_inode_info *}; arg3:size_t; arg4:DWord):ssize_t; cdecl;
end;
end;
Pproc_dir_entry = ^proc_dir_entry;
Pproc_dir_entry = ^proc_dir_entry;
proc_dir_entry = record
proc_dir_entry = record
low_ino:Cardinal;
low_ino:Cardinal;
namelen:Integer;
namelen:Integer;
name:PChar;
name:PChar;
mode:mode_t;
mode:mode_t;
nlink:nlink_t;
nlink:nlink_t;
uid:uid_t;
uid:uid_t;
gid:gid_t;
gid:gid_t;
size:loff_t;
size:loff_t;
proc_iops:Pointer;{const struct inode_operations *}
proc_iops:Pointer;{const struct inode_operations *}
proc_fops:Pfile_operations;{const struct file_operations *}
proc_fops:Pfile_operations;{const struct file_operations *}
get_info:Pointer;{get_info_t *}
get_info:Pointer;{get_info_t *}
owner:Pointer;{struct module *}
owner:Pointer;{struct module *}
next, parent, subdir:Pproc_dir_entry;
next, parent, subdir:Pproc_dir_entry;
data:Pointer;
data:Pointer;
read_proc:Pointer;{read_proc_t *}
read_proc:Pointer;{read_proc_t *}
write_proc:Pointer;{write_proc_t *}
write_proc:Pointer;{write_proc_t *}
count:atomic_t;{use count}
count:atomic_t;{use count}
deleted:LongInt;{delete flag}
deleted:LongInt;{delete flag}
_set:Pointer;
_set:Pointer;
end;
end;
var
var
proc_root:proc_dir_entry; cvar; external;
proc_root:proc_dir_entry; cvar; external;
//function copy_from_user(_to:Pointer; _from:Pointer; count:Cardinal):Cardinal; cdecl;
//function copy_from_user(_to:Pointer; _from:Pointer; count:Cardinal):Cardinal; cdecl;
function create_proc_entry(name:PChar; mode:mode_t; parent:Pproc_dir_entry):Pproc_dir_entry; cdecl;
function create_proc_entry(name:PChar; mode:mode_t; parent:Pproc_dir_entry):Pproc_dir_entry; cdecl;
procedure remove_proc_entry(name:PChar; parent:Pproc_dir_entry); cdecl;
procedure remove_proc_entry(name:PChar; parent:Pproc_dir_entry); cdecl;
procedure printk(fmt:PChar); cdecl;
procedure printk(fmt:PChar); cdecl;
procedure printk(fmt:PChar; param:LongInt); cdecl;
procedure printk(fmt:PChar; param:LongInt); cdecl;
procedure printk(fmt:PChar; param1:PChar); cdecl;
procedure printk(fmt:PChar; param1:PChar); cdecl;
procedure printk(fmt:PChar; param1:PChar; param2:LongInt); cdecl;
procedure printk(fmt:PChar; param1:PChar; param2:LongInt); cdecl;
function register_chrdev(devMajor:LongInt; devName:PChar; fops:Pfile_operations):LongInt; cdecl;
function register_chrdev(devMajor:LongInt; devName:PChar; fops:Pfile_operations):LongInt; cdecl;
function unregister_chrdev(devMajor:LongInt; devName:PChar):LongInt; cdecl;
function unregister_chrdev(devMajor:LongInt; devName:PChar):LongInt; cdecl;
 
implementation
implementation
{$LINK kernel_module_info}
{$LINK kernel_module_info}
//function copy_from_user(_to:Pointer; _from:Pointer; count:Cardinal):Cardinal; cdecl; external;
 
function create_proc_entry(name:PChar; mode:mode_t; parent:Pproc_dir_entry):Pproc_dir_entry; cdecl; external;
//function copy_from_user(_to:Pointer; _from:Pointer; count:Cardinal):Cardinal; cdecl; external;
procedure remove_proc_entry(name:PChar; parent:Pproc_dir_entry); cdecl; external;
function create_proc_entry(name:PChar; mode:mode_t; parent:Pproc_dir_entry):Pproc_dir_entry; cdecl; external;
procedure printk(fmt:PChar); cdecl; external;
procedure remove_proc_entry(name:PChar; parent:Pproc_dir_entry); cdecl; external;
procedure printk(fmt:PChar; param:LongInt); cdecl; external;
procedure printk(fmt:PChar); cdecl; external;
procedure printk(fmt:PChar; param1:PChar); cdecl; external;
procedure printk(fmt:PChar; param:LongInt); cdecl; external;
procedure printk(fmt:PChar; param1:PChar; param2:LongInt); cdecl; external;
procedure printk(fmt:PChar; param1:PChar); cdecl; external;
function register_chrdev(devMajor:LongInt; devName:PChar; fops:Pfile_operations):LongInt; cdecl; external;
procedure printk(fmt:PChar; param1:PChar; param2:LongInt); cdecl; external;
function unregister_chrdev(devMajor:LongInt; devName:PChar):LongInt; cdecl; external;
function register_chrdev(devMajor:LongInt; devName:PChar; fops:Pfile_operations):LongInt; cdecl; external;
end.
function unregister_chrdev(devMajor:LongInt; devName:PChar):LongInt; cdecl; external;
end.
</code>
</code>

Revision as of 10:37, 5 October 2007

overview

The purpose of this page is to give basic material to write Linux kernel modules using FPC. As Linux distributions may differ, most actions on installing packages are described for Debian distribution, on with author of this article is working. However, it may be very simple to translate this for other Linux distributions.

Requirements

1) First of all, you need to have FPC installed

apt-get install fp-compiler

Please notice that this will install fp-compiler and fp-units-rtl. The author of this page is using 2.2.0, but 2.0.4 is also working. However other versions were not tested an my not work, especially previous releases. 2) you need to have kernel headers packages installed

apt-get install linux-headers-$(uname -r)

3) Then you need make utility

apt-get install make

Please note that installing linux-headers-* will install automatically the required version of GCC and binutils.

Kernel RTL

It is obvious that when programming Linux kernel modules, one can not use the standard FPC RTL. As nos standard kernel RTL is provided, you have to write your own one. This is not very easy. A good start point could be the following

unit system;
{$TYPEINFO OFF}
interface
{Paѕcal common type aliases}
type
	{Basic embedded types}
	u8 = Byte;
	u16 = Word;
	u32 = LongWord;
	u64 = QWord;
	s8 = ShortInt;
	s16 = SmallInt;
	s32 = LongInt;
	s64 = Int64;
	{Integer types}
	DWord = LongWord;
	Cardinal = LongWord;
	Integer = SmallInt;
	UInt64 = QWord;
{$ifdef CPU64}
	SizeInt = Int64;
	SizeUInt = QWord;
	PtrInt = Int64;
	PtrUInt = QWord;
	ValSInt = int64;
	ValUInt = qword;
{$endif CPU64}
{$ifdef CPU32}
	SizeInt = Longint;
	SizeUInt = DWord;
	PtrInt = Longint;
	PtrUInt = DWord;
	ValSInt = Longint;
	ValUInt = Cardinal;
{$endif CPU32}
	{Zero - terminated strings }
	PChar = ^Char;
	PPChar = ^PChar;
	{Pointers}
	PSmallInt = ^Smallint;
	PShortInt = ^Shortint;
	PInteger  = ^Integer;
	PByte     = ^Byte;
	PWord     = ^word;
	PDWord    = ^DWord;
	PLongWord = ^LongWord;
	PLongint  = ^Longint;
	PCardinal = ^Cardinal;
	PQWord    = ^QWord;
	PInt64    = ^Int64;
	PPtrInt   = ^PtrInt;
	PPtrUInt  = ^PtrUInt;
	PSizeInt  = ^SizeInt;
	PPointer  = ^Pointer;
	PPPointer = ^PPointer;
	PBoolean  = ^Boolean;
	PWordBool = ^WordBool;
	PLongBool = ^LongBool;
	{Other types}
	HRESULT = type Longint;
	TDateTime = type Double;
	TError = type Longint;
const
	KERN_INFO='KERNEL:INFO:';
	KERN_ALERT='KERNEL:ALERT:';
	DEVICE_NAME='kpmod';
	EPERM = 1;{Operation not permitted}
	ENOENT = 2;{No such file or directory}
	ESRCH = 3;{No such process}
	EINTR = 4;{Interrupted system call}
	EIO = 5;{I/O error}
	ENXIO = 6;{No such device or address}
	E2BIG = 7;{Argument list too long}
	ENOEXEC = 8;{Exec format error}
	EBADF = 9;{Bad file number}
	ECHILD = 10;{No child processes}
	EAGAIN = 11;{Try again}
	ENOMEM = 12;{Out of memory}
	EACCES = 13;{Permission denied}
	EFAULT = 14;{Bad address}
	ENOTBLK = 15;{Block device required}
	EBUSY = 16;{Device or resource busy}
	EEXIST = 17;{File exists}
	EXDEV = 18;{Cross-device link}
	ENODEV = 19;{No such device}
	ENOTDIR = 20;{Not a directory}
	EISDIR = 21;{Is a directory}
	EINVAL = 22;{Invalid argument}
	ENFILE = 23;{File table overflow}
	EMFILE = 24;{Too many open files}
	ENOTTY = 25;{Not a typewriter}
	ETXTBSY = 26;{Text file busy}
	EFBIG = 27;{File too large}
	ENOSPC = 28;{No space left on device}
	ESPIPE = 29;{Illegal seek}
	EROFS = 30;{Read-only file system}
 	EMLINK = 31;{Too many links}
	EPIPE = 32;{Broken pipe}
	EDOM = 33;{Math argument out of domain of func}
	ERANGE = 34;{Math result not representable}
type
	{Kernel types}
	mode_t = Word;
	nlink_t = DWord;
	uid_t = Word;
	fl_owner_t = ^files_struct;
 	gid_t = Word;
	off_t = LongInt;
	loff_t = Int64;

Ploff_t = ^loff_t;

	size_t = DWord;
	ssize_t = LongInt;
	{$PACKRECORDS C}
	atomic_t = record
		counter:LongInt;
	end;
	files_struct = record
  		{read mostly part}
		count:atomic_t;
		//struct fdtable *fdt;
		//struct fdtable fdtab;
  		{written part on a separate cache line in SMP}
		//spinlock_t file_lock ____cacheline_aligned_in_smp;
		//int next_fd;
		//struct embedded_fd_set close_on_exec_init;
		//struct embedded_fd_set open_fds_init;
		//struct file * fd_array[NR_OPEN_DEFAULT];
 	end;
	filldir_t = function(arg1:Pointer; arg2:PChar; arg3:LongInt; arg4:loff_t; arg5:u64; arg6:DWord):LongInt; cdecl;
	read_actor_t = function(arg1:Pointer{read_descriptor_t *}; arg2:Pointer{struct page *}; arg3:DWord; arg4:DWord):LongInt; cdecl;
	Pfile_operations = ^file_operations;
	file_operations = record
		owner:Pointer;{struct module *}
		llseek:function(filp:Pointer{struct file *}; offset:loff_t; whence:LongInt):loff_t; cdecl;
		read:function(filp:Pointer{struct file *}; buf:PChar; count:size_t; offset:Ploff_t):ssize_t; cdecl;
		write:function(filp:Pointer{struct file *}; buf:PChar; count:size_t; offset:Ploff_t):ssize_t; cdecl;
		aio_read:function(kiocb:Pointer{struct kiocb *}; iovec:Pointer{const struct iovec *}; count:DWord; offset:loff_t):ssize_t; cdecl;
		aio_write:function(kiocb:Pointer{struct kiocb *}; iovec:Pointer{const struct iovec *}; count:DWord; offset:loff_t):ssize_t; cdecl;
		readdir:function(filp:Pointer{struct file *}; buf:Pointer; filldir:filldir_t):LongInt; cdecl;
		poll:function(filp:Pointer{struct file *}; poll_table:Pointer{struct poll_table_struct *}):DWord; cdecl;
		ioctl:function(inode:Pointer{struct inode *}; filp:Pointer{struct file *}; arg1:DWord; arg2:DWord):LongInt; cdecl;
		unlocked_ioctl:function(filp:Pointer{struct file *}; arg1:DWord; arg2:DWord):LongInt; cdecl;
		compat_ioctl:function(filp:Pointer{struct file *}; arg1:DWord; arg2:DWord):LongInt; cdecl;
		mmap:function(filp:Pointer{struct file *}; vm_area_struct:Pointer{ struct vm_area_struct *}):LongInt; cdecl;
		open:function(inode:Pointer{struct inode *}; filp:Pointer{struct file *}):LongInt; cdecl;
		flush:function(filp:Pointer{struct file *}; id:fl_owner_t):LongInt; cdecl;
		release:function(inode:Pointer{struct inode *}; filp:Pointer{struct file *}):LongInt; cdecl;
		fsync:function(filp:Pointer{struct file *}; arg1:Pointer{ struct dentry *}; datasync:LongInt):LongInt; cdecl;
		aio_fsync:function(kiocb:Pointer{struct kiocb *}; datasync:LongInt):LongInt; cdecl;
		fasync:function(arg1:LongInt; filp:Pointer{struct file *}; arg2:LongInt):LongInt; cdecl;
		lock:function(filp:Pointer{struct file *}; arg1:LongInt; arg2:Pointer{ struct file_lock *}):LongInt; cdecl;
		sendfile:function(filp:Pointer{struct file *}; arg1:Pointer{ loff_t *}; arg2:size_t; arg3:read_actor_t; arg4:Pointer{ void *}):ssize_t; cdecl;
		sendpage:function(filp:Pointer{struct file *}; arg1:Pointer{ struct page *}; arg2:LongInt; arg3:size_t; arg4:Pointer{ loff_t *}; arg5:LongInt):ssize_t; cdecl;
		get_unmapped_area:function(filp:Pointer{struct file *}; arg1:DWord; arg2:DWord; arg3:DWord; arg4:DWord):DWord; cdecl;
		check_flags:function(falgs:LongInt):LongInt; cdecl;
		dir_notify:function(filp:Pointer{struct file *}; arg:DWord):LongInt; cdecl;
		flock:function(filp:Pointer{struct file *}; arg1:LongInt; arg2:Pointer{ struct file_lock *}):LongInt; cdecl;
		splice_write:function(arg1:Pointer{struct pipe_inode_info *}; filp:Pointer{struct file *}; arg2:Pointer{ loff_t *}; arg3:size_t; arg4:DWord):ssize_t; cdecl;
		splice_read:function(filp:Pointer{struct file *}; arg1:Pointer{ loff_t *}; arg2:Pointer{ struct pipe_inode_info *}; arg3:size_t; arg4:DWord):ssize_t; cdecl;
	end;
	Pproc_dir_entry = ^proc_dir_entry;
	proc_dir_entry = record
		low_ino:Cardinal;
		namelen:Integer;
		name:PChar;
		mode:mode_t;
		nlink:nlink_t;
		uid:uid_t;
		gid:gid_t;
		size:loff_t;
		proc_iops:Pointer;{const struct inode_operations *}
		proc_fops:Pfile_operations;{const struct file_operations *}
		get_info:Pointer;{get_info_t *}
		owner:Pointer;{struct module *}
		next, parent, subdir:Pproc_dir_entry;
		data:Pointer;
		read_proc:Pointer;{read_proc_t *}
		write_proc:Pointer;{write_proc_t *}
		count:atomic_t;{use count}
		deleted:LongInt;{delete flag}
		_set:Pointer;
	end;
var
	proc_root:proc_dir_entry; cvar; external;
//function copy_from_user(_to:Pointer; _from:Pointer; count:Cardinal):Cardinal; cdecl;
function create_proc_entry(name:PChar; mode:mode_t; parent:Pproc_dir_entry):Pproc_dir_entry; cdecl;
procedure remove_proc_entry(name:PChar; parent:Pproc_dir_entry); cdecl;
procedure printk(fmt:PChar); cdecl;
procedure printk(fmt:PChar; param:LongInt); cdecl;
procedure printk(fmt:PChar; param1:PChar); cdecl;
procedure printk(fmt:PChar; param1:PChar; param2:LongInt); cdecl;
function register_chrdev(devMajor:LongInt; devName:PChar; fops:Pfile_operations):LongInt; cdecl;
function unregister_chrdev(devMajor:LongInt; devName:PChar):LongInt; cdecl;
implementation
{$LINK kernel_module_info}
//function copy_from_user(_to:Pointer; _from:Pointer; count:Cardinal):Cardinal; cdecl; external;
function create_proc_entry(name:PChar; mode:mode_t; parent:Pproc_dir_entry):Pproc_dir_entry; cdecl; external;
procedure remove_proc_entry(name:PChar; parent:Pproc_dir_entry); cdecl; external;
procedure printk(fmt:PChar); cdecl; external;
procedure printk(fmt:PChar; param:LongInt); cdecl; external;
procedure printk(fmt:PChar; param1:PChar); cdecl; external;
procedure printk(fmt:PChar; param1:PChar; param2:LongInt); cdecl; external;
function register_chrdev(devMajor:LongInt; devName:PChar; fops:Pfile_operations):LongInt; cdecl; external;
function unregister_chrdev(devMajor:LongInt; devName:PChar):LongInt; cdecl; external;
end.