i am trying to figure out how the code behind a basic kernel driver works.
I have the following struct:
static struct file_operations fops =
{
.open = dev_open,
.read = dev_read,
.write = dev_write,
.release = dev_release,
};
And my dev_open function is defined as:
static int dev_open(struct inode *, struct file *);
Now Im also familiar with the fact that the prototype for opening a device file is defined in the linux/fs.h:
http://lxr.linux.no/linux+v3.10/include/linux/fs.h#L1517
Here is the specific line from that link:
int (*open) (struct inode *, struct file *);
Now my question is what is the relationship between .open = dev_open, and int (*open) (struct inode *, struct file *);
which is defined in linux/fs.h? Is it passing the address of dev_open to the function pointer int (*open) defined in the linux/fs.h? There must be some relation or what is the point of defining the struct fops as type "file operation"?
A similar question was asked and answered here but i feel that my question was left out:
File operations in drivers
Thank you
I think this question is more about C than the Linux kernel.
Members of structure or union types cannot have function type, but they can have pointer to function type. For example, in the Linux kernel, the open member of struct file_operations needs to be declared with a pointer to function type: int (*open)(struct inode *, struct file *);. Declaring the member as int open(struct inode *, struct file *); is an error.
In this variable definition in Linux kernel code:
static struct file_operations fops =
{
.open = dev_open,
.read = dev_read,
.write = dev_write,
.release = dev_release,
};
Incidentally, the above should normally have the owner member initialized like so:
.owner = THIS_MODULE,
The expressions dev_open, dev_read, dev_write and dev_release are function designators being used as assignment expressions to initialize the members of fops. A function designator is an expression that has function type. Unless it is the operand of sizeof, _Alignof, or the unary & operator, a function designator is converted to a pointer to function type. Therefore, the above definition of variable foo is exactly equivalent to:
static struct file_operations fops =
{
.open = &dev_open,
.read = &dev_read,
.write = &dev_write,
.release = &dev_release,
};
(Don't forget to also initialize .owner = THIS_MODULE,.)
There, the function designators are operands of the unary & operator and so are not converted to pointer to function types implicitly, but the & operator is converting them to pointer to function types explicitly.
After the above initialization of fops, rc = fops.open(inode, file); indirectly calls dev_open(inode, file) and assigns the return value to rc. You may sometimes see this written in an older style: rc = (*fops.open)(inode, file);. They both do the same thing. The operand of the function call operator ( ) is in fact always a pointer to a function. In the case of rc = (*fops.open)(inode, file);, fops.open has a pointer to a function type. (*fops.open) dereferences fops.open to a function type but since (*fops.open) is a function designator it is implicitly converted back to a pointer to function type before the function call. Similarly, in the direct call rc = dev_open(inode, file);, dev_open is a function designator and so has a function type, but is implicitly converted to a pointer to function type before the function call.
Related
Let's say I have a function defined in Rust, which looks like this:
#[no_mangle]
pub unsafe extern "C" fn do_something(
my_value: *mut MyStruct,
some_param: c_uint,
content: *mut *mut u8,
length: *mut c_uint,
capacity: *mut c_uint,
) -> *mut MyStruct {
// Do something and obtain an `ffi_result`...
let heap_data = ffi_result.as_mut_ptr();
// These values are passed as "out" parameters.
*length = ffi_result.len() as c_uint;
*capacity = ffi_result.capacity() as c_uint;
*content = heap_data;
// We intentionally "leak" this data to the heap.
// The caller is responsible for cleaning it up by calling another function.
std::mem::forget(ffi_result);
std::boxed::Box::into_raw(value_of_type_my_struct)
}
It takes in a pointer to a struct, a simple integer parameter, several out parameters that can later be used to create an Array and it returns a pointer to a struct.
Now I compile the rust library into a static library for the target aarch64-apple-ios. I set up a XCode project, add the static library as a dependency as explained here with an "Objective-C Bridging Header" where I import the following header file
#ifndef libmy_project_h
#define libmy_project_h
#include <stdint.h>
struct myStruct;
struct myStruct *do_something(struct myStruct *state, int someParam, char **content, int *length, int *capacity);
#endif
Up until this point everything seems to work fine and I have already successfully used this procedure for a whole bunch of other functions. However in this special case I can not figure out how to call this function from swift. I need to call the function from swift and pass content, length and capacity as out parameters so that I can later use the pointers to create an Array in Swift like so.
This is what I tried so far:
var content = UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>(UnsafeMutablePointer(bitPattern: 0))
var length = UnsafeMutablePointer<Int32>(bitPattern: 0)
var capacity = UnsafeMutablePointer<Int32>(bitPattern: 0)
let my_struct = do_something(my_struct, Int32(some_param), content, length, capacity)
let buffer = UnsafeRawBufferPointer(start: content?.pointee, count: Int(length!.pointee))
var data = Array(repeating: UInt8(0), count: Int(length!.pointee))
data.withUnsafeMutableBytes { arrayPtr in
arrayPtr.copyBytes(from: buffer)
}
However now when I execute this swift snippet, I get an EXC_BAD_ACCESS error, which I think occurs because the pointers I manually created do not belong to the adress space of my application. How can I create pointers that I can use as out parameters?
P.S. For reference here is the same interop code in C#:
[DllImport("my_dll")]
private static extern IntPtr do_something(IntPtr state, uint someParam, out IntPtr content, out uint length, out uint capacity);
Which can be called like so:
IntPtr contentPointer;
uint length, capacity;
IntPtr my_struct = do_something(state, myParam, out contentPointer, out length, out capacity);
byte[] rawContent = new byte[length];
Marshal.Copy(contentPointer, rawContent, 0, (int)length);
// Free the data owned by rust with another FFI call:
free_do_something_result(contentPointer, length, capacity);
var length = UnsafeMutablePointer<Int32>(bitPattern: 0)
You need to pass storage for your out-parameters. This is defining a null pointer. When Rust tries to write the result to address 0, it crashes, since you don't have access to write there.
Instead of creating two layers of pointers, create a value of the type you want, and then pass the address (&) of that value; this will add the extra layer of pointer automatically.
// Create storage
var content: UnsafeMutablePointer<CChar>? // Could be NULL, so Optional
var length: Int32 = 0
var capacity: Int32 = 0
// Pass as references
do_something(&content, &length, &capacity)
// Copy the data
let data = Array(UnsafeRawBufferPointer(start: content, count: Int(length)))
content is still a pointer here because the thing being updated is a pointer. You're not providing storage for content, Rust is. But you do need to provide storage for the pointer (and that's what this does).
I can't compile your code because it's missing a lot (an MCVE would be much better here), so I can't test that this is doing exactly what you mean, but it should be close.
In your example, you're leaking the memory, but since your C# calls free_do_something_result (which I assume cleans it up), I assume you're actually doing the same in the Swift.
I had this weird problem in Dart. Consider the following code :
class Number {
int num = 10;
}
Here, I created a little class with a int object num
When I try to print it using the main() function OUTSIDE the class like :
main() {
print(num);
}
I get the output as :
num
Which is weird, since I expected an error. If I were to print a undefined variable as in print(foo); I would get an error, which is expected.
What I find even more interesting is the runtimeType of a variable whose value is num.
var temp = num;
print(temp.runtimeType);
}
The above code prints _Type, when I expected it to be int.
Can somebody please clear this?
The name num is a type declared in dart:core. It's the supertype of int and double.
When you do print(num); outside the scope where your int num; variable is declared, the num refers to that type from dart:core which is always imported and therefore in scope.
Dart type names can be used as expressions, they evaluate to a Type object.
So, you are printing a Type object for the type num, which prints "num", and the run-time type of that object, which is again a Type object, which prints _Type because that's the actual internal type of the Type object instance.
let cfg: UnsafeMutablePointer <pjsua_config> = nil;
pjsua_config_default(cfg);
cfg.cb // Error: Value of type 'UnsafeMutablePointer<pjsua_config>' has no member 'cb'
How to cast cfg to access it's fields ? I've tried to find answer in Apple's 'Interacting with C API' document
but there is no info related to this issue.
Actually there is related information in the "Interacting with C APIs"
chapter:
When a function is declared as taking an UnsafeMutablePointer<Type> argument, it can accept any of the following:
...
An inout expression whose operand is a stored lvalue of type Type, which is passed as the address of the lvalue
...
So you can simply pass the address of an (initialized) pjsua_config structure as "inout-parameter" with &, similar as you would do in C:
var cfg = pjsua_config() // creates a `struct pjsua_config` with all fields set to zero
pjsua_config_default(&cfg)
Now you can access cfg.cb, and you don't have to worry about
memory management.
I don't know what you are doing in
pjsua_config_default() method but to get raw data you shud call memory on your pointer.
Please see working example:
var pt : UnsafeMutablePointer<Int>? // Optional
pt = UnsafeMutablePointer.alloc(1)
pt!.initialize(22)
pt!.memory // returns your value
// Cleanup
pt!.destroy()
pt!.dealloc(1)
pt! = nil
I want to use a C function in Swift, which has the following method definition:
int startTest(char *test1, char* test2)
If I call this method from my Swift code like this
startTest("test1", "test2")
I get the following error message:
'String' is not convertible to 'UnsafeMutablePointer<Int8>'
If I change my method definition to:
int startTest(const char *test1, const char* test2)
and call that method like this:
var test1 = "test1"
var test2 = "test2"
startTest(&test1, &test2)
I get
'String' is not identical to 'Int8'
So my question is: how can I use the C function? (it is part of a library, so changing the method call could be problematic).
Thanks in advance!
In the case of
int startTest(const char *test1, const char* test2);
you can call the function from Swift simply as
let result = startTest(test1, test2)
(without the address-of operators). The Swift strings are converted automatically
to C Strings for the function call
In the case of
int startTest(char *test1, char* test2);
you need to call the function with a (variable) Int8 buffer, because the Swift
compiler must assume that the strings might be modified from the C function.
Example:
var cString1 = test1.cStringUsingEncoding(NSUTF8StringEncoding)!
var cString2 = test2.cStringUsingEncoding(NSUTF8StringEncoding)!
let result = startTest(&cString1, &cString2)
What is the purpose of union in the yacc file? Is it directly related to yylval in the flex file? If you don't use yylval, then you don't need to use union?
The purpose of the union is to allow storing different kind of objects into nodes emitted by flex.
To explain better you can have for example:
%union
{
int intValue;
float floatValue;
char *stringValue;
}
in .y if you want to provide basic support for int, float and string types. What can you do with this?
Two things:
First, you can automatically set right values when generating tokens. Think about .l file of the previous example, you can have:
[a-zA-Z][a-zA-Z0-9]* {
yylval.stringValue = strdup(yytext);
return IDENTIFIER;
}
[0-9]+ {
yylval.intValue = atoi(yytext);
return INTEGER;
}
[0-9]*\.[0-9]+"f"? {
yylval.floatValue = new atof(yytext);
return FLOAT;
}
In addition you can use value directly in your flex grammar:
nexp: nexp '+' nexp { $<floatValue>$ = $<floatValue>1 + $<floatValue>3 }
Finally if you plan to use an OOP syntax tree you can define union as
%union
{
class ASTNode *node;
}
in which ASTNode is the ancestor class of any kind of syntax node.
The %union declaration modifies the type of yylval.
The bison manual explains:
In an ordinary (nonreentrant) parser, the semantic value of the token must be stored into the global variable yylval. When you are using just one data type for semantic values, yylval has that type. Thus, if the type is int (the default), you might write this in yylex:
...
yylval = value; /* Put value onto Bison stack. */
return INT; /* Return the type of the token. */
...
When you are using multiple data types, yylval's type is a union made from the %union declaration (see section The Collection of Value Types). So when you store a token's value, you must use the proper member of the union. If the %union declaration looks like this:
%union {
int intval;
double val;
symrec *tptr;
}
then the code in yylex might look like this:
...
yylval.intval = value; /* Put value onto Bison stack. */
return INT; /* Return the type of the token. */
...