Recently I have found the following piece of code in the linux kernel tree, commit adfa0fa1dd3cdbccec9597fe53b6177a9aa6e20f2f8; linux/kernel/sched/deadline.c; at the very bottom there is a construct which is pasted below. Please tell me is this some syntax to represent a class, and which compiler do I use to have the code compiled?
{
.next = &rt_sched_class,
.enqueue_task = enqueue_task_dl,
.dequeue_task = dequeue_task_dl,
.yield_task = yield_task_dl,
.check_preempt_curr = check_preempt_curr_dl,
.pick_next_task = pick_next_task_dl,
.put_prev_task = put_prev_task_dl,
#ifdef CONFIG_SMP
.select_task_rq = select_task_rq_dl,
.set_cpus_allowed = set_cpus_allowed_dl,
.rq_online = rq_online_dl,
.rq_offline = rq_offline_dl,
.pre_schedule = pre_schedule_dl,
.post_schedule = post_schedule_dl,
.task_woken = task_woken_dl,
#endif
.set_curr_task = set_curr_task_dl,
.task_tick = task_tick_dl,
.task_fork = task_fork_dl,
.task_dead = task_dead_dl,
.prio_changed = prio_changed_dl,
.switched_from = switched_from_dl,
.switched_to = switched_to_dl,
}
Class is a term applicable to C++, not C. What you see is a struct, initialized via designators.
Linux Kernel is written in C (mostly) and is buildable with GCC compiler.
What you see is a normal structure initialization using designated initializers.
The Linux kernel is almost all plain C, but often uses GCC-specific extensions. Designated initializers is not an extension, they are a plain standard C feature and was introduced in the C99 standard.
Related
In windows I used
__try {
__int64(__fastcall * calladdress)(__int64, __int64);
calladdress = (__int64*)par1;
returnvalue = calladdress(par2, par3);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
returnvalue = 0;
}
In linux,
ptr64 functionaddr = data[0];
ptr64 par1 = data[1];
ptr64 par2 = data[2];
void * returnAddr = (void*) data[3];
ptr64(__fastcall* calladdress(ptr64,ptr64);
calladdress = (ptr64*)functionaddr;
*(ptr64*)returnAddr = calladdress(par1,par2);
Error: expected ')' befor '*' token
ptr64(__fastcall* calladdress(ptr64,ptr64);
^ here
Sorry for newbie question, but I don't know much about gcc.
It worked well in Windows, but I don't know how to compile this code on Linux.
If you know how to solve this problem, please reply.
First of all, I don't know much about Linux, so I can't guarantee that my answer is exactly right.
Just a quick search showed that the Linux kernel seems to be using fastcall like this.
#define FASTCALL(x) x __attribute__((regparm(3)))
#define fastcall __attribute__((regparm(3)))
More references:
x86 gcc compiled assembly code: fastcall behavior
In pure C code in different projects that involve Postgresql server programming which I'm working with now, I keep encountering the function "IsA()" which returns a boolean and checks whether or not 2 instances of a struct belong to the same struct. I suppose.
One of them:
https://github.com/guotao0628/pipelinedb/blob/master/src/backend/executor/nodeBitmapAnd.c#L123
for (i = 0; i < nplans; i++)
{
PlanState *subnode = bitmapplans[i];
TIDBitmap *subresult;
subresult = (TIDBitmap *) MultiExecProcNode(subnode);
if (!subresult || !IsA(subresult, TIDBitmap)) /*what's IsA(...) ? */
elog(ERROR, "unrecognized result from subplan");
if (result == NULL)
result = subresult; /* first subplan */
I need to port some of that C code to other strictly typed language. Hence, I need to know how "isA()" is implemented under the hood. But I haven't found it anywhere. Supposedly it's defined in some library.
Where can I find its definition?
IsA is a macro which is defined in this header file in Postgresql source code.
Hi I am following the book Linux device driver development to write a driver in Linux. In an example code as below:
struct my_gpios {
int reset_gpio;
int led_gpio;
};
static struct my_gpiosneeded_gpios = {
.reset_gpio = 47;
.led_gpio = 41;
};
static struct resource needed_resources[] = {
[0] = { /* The first memory region */
.start = JZ4740_UDC_BASE_ADDR,
.end = JZ4740_UDC_BASE_ADDR + 0x10000 - 1,
.flags = IORESOURCE_MEM,
.name = "mem1",
},
[1] = {
.start = JZ4740_UDC_BASE_ADDR2,Platform Device Drivers
[ 126 ]
.end = JZ4740_UDC_BASE_ADDR2 + 0x10000 -1,
.flags = IORESOURCE_MEM,
.name = "mem2",
},
};
static struct platform_devicemy_device = {
.name = "my-platform-device",
.id = 0,
.dev = {
.platform_data = &needed_gpios,
},
.resource = needed_resources,
.num_resources = ARRY_SIZE(needed_resources),
};
platform_device_register(&my_device);
I do not understand the syntax static struct_gpiosneeded_gpios = {} meaning and why have a dot in .reset_gpio. And what is the meaning of the syntax static struct [] = {[0]={}, [1]={}}?
Could you please give me a reference link or keyword or example about static struct {.a = VALUE, .b = VALUE,};?
static struct something x = {
.field_one = 123,
.field_two = 456
};
This is a struct initialization syntax, standard from C99 (see here). This example creates a variable of type struct something named x, with fields field_one and field_two initialized to the specified values, and any other field initialized to 0. The static keyword is a storage duration specifier (see here).
static struct something x[] = {[0]={ ... }, [1]={ ... }};
This is a mix of both struct initialization and array initialization syntax, again standard from C99 (see here). This example creates an array x of variables of type struct something, the one at index 0 is initialized with the contents of the {...} initializer, and the same goes for the one at index 1. Since the greatest specified index is 1, the array size is 2.
I do not understand why they named the type is u32 or what is the purpose of __raw.
The u32 type is just a short alias for uint32_t.
I am not sure exactly where you saw __raw, since I don't seem to find anything like it in the kernel source. In any case, the Linux kernel as a series of compile-time annotations used for variables that have different purposes (__user, __rcu, etc). Those are not part of the C standard and frequently not even GCC extensions. They are mostly hints to be used by Sparse, the Linux kernel semantic checker.
Is there any standard or rule for naming the variable, macro, type,... in kernel?
Refer to the Linux kernel coding style documentation page for more information. I would suggest you to read it all before trying to do any kind of kernel programming. The more documentation pages you read, the better.
And what C standard i have to compliance when writing code in linux driver?
Use anything that is C99 or older and you will be fine. The Linux kernel code does not adhere to a single C standard, and various parts of the code aren't even standard compliant, but use GCC extensions. See here for more information.
You don't usually choose the standard when compiling, the kernel Makefile does this for you, and it should default to C90.
In any case, those are a lot of questions. If you have a specific question I would suggest you to ask it separately so that people are able to give you a focused and more extensive answer, since it's off topic to ask too broad or too many questions.
I am a beginner in library linking and have spent two days trying to link the libcrypto library to my C program on Visual Studio 2017.
I have had to include applink.c to solve my issues. But I think it is very weird to include something which is not a header. After searching a bit on the internet, I learnt that including a source file is something that exist but that one should avoid doing. Why then the openssl library does not ?
I don't think it is particularly relevant, but here is a small overview of this source file, you can find the whole source file here.
#define APPLINK_OPEN 18 /* formally can't be used, as flags can vary */
#define APPLINK_READ 19
#define APPLINK_WRITE 20
#define APPLINK_LSEEK 21
#define APPLINK_CLOSE 22
#define APPLINK_MAX 22 /* always same as last macro */
#ifndef APPMACROS_ONLY
# include <stdio.h>
# include <io.h>
# include <fcntl.h>
static void *app_stdin(void)
{
return stdin;
}
static void *app_stdout(void)
{
return stdout;
}
if (once) {
OPENSSL_ApplinkTable[APPLINK_STDIN] = app_stdin;
OPENSSL_ApplinkTable[APPLINK_STDOUT] = app_stdout;
OPENSSL_ApplinkTable[APPLINK_STDERR] = app_stderr;
OPENSSL_ApplinkTable[APPLINK_FPRINTF] = fprintf;
OPENSSL_ApplinkTable[APPLINK_FGETS] = fgets;
OPENSSL_ApplinkTable[APPLINK_FREAD] = fread;
OPENSSL_ApplinkTable[APPLINK_FWRITE] = fwrite;
OPENSSL_ApplinkTable[APPLINK_FSETMOD] = app_fsetmod;
OPENSSL_ApplinkTable[APPLINK_FEOF] = app_feof;
OPENSSL_ApplinkTable[APPLINK_FCLOSE] = fclose;
OPENSSL_ApplinkTable[APPLINK_FOPEN] = fopen;
OPENSSL_ApplinkTable[APPLINK_FSEEK] = fseek;
OPENSSL_ApplinkTable[APPLINK_FTELL] = ftell;
OPENSSL_ApplinkTable[APPLINK_FFLUSH] = fflush;
OPENSSL_ApplinkTable[APPLINK_FERROR] = app_ferror;
OPENSSL_ApplinkTable[APPLINK_CLEARERR] = app_clearerr;
OPENSSL_ApplinkTable[APPLINK_FILENO] = app_fileno;
OPENSSL_ApplinkTable[APPLINK_OPEN] = _open;
OPENSSL_ApplinkTable[APPLINK_READ] = _read;
OPENSSL_ApplinkTable[APPLINK_WRITE] = _write;
OPENSSL_ApplinkTable[APPLINK_LSEEK] = _lseek;
OPENSSL_ApplinkTable[APPLINK_CLOSE] = _close;
once = 0;
}
What is the difference between including a header and a source file ? What are the cons and pros to do that ?
This post isn't asking for a way to fix the link problems
Including a file is just like copying the file into your C file.
This means that anything that includes the C file will have its own sort of copy of the functions in applink.c.
You'll also notice that they're declared 'static', meaning that these copies are local to their respective files, and cannot create conflicts. They'll likely be inlined, even.
In general, this is a trade-off between binary size and compile time on one hand, and runtime speed and code simplicity on the other.
This isn't a rare thing to see, what surprises me more is that it's .c and not .h.
Where is the implementation of the function dm_task_create in cryptsetup (and other dm_task_ related functions)? Grepping for this function in the source for cryptsetup I come up with nothing. I see it is used in lib/libdevmapper.c and that it has a function prototype in libdevmapper.h. However where is the implementation? As a side note, cryptsetup compiles fine and executes.
Just to check, I grepped through the kernel source as well but it doesn't appear to be implemented in the kernel either.
From the following link http://www.saout.de/pipermail/dm-crypt/2009-December/000464.html it appears that at least in the past it was implemented in libdevmapper.c.
It's implemented in libdm-common.c, which is part of libdm (lib device-mapper). It is not implemented as part of cryptsetup itself.
This code is maintained alongside LVM2, as documented on this page:
The userspace code (dmsetup and libdevmapper) is now maintained
alongside the LVM2 source available from
http://sources.redhat.com/lvm2/. To build / install it without LVM2
use 'make device-mapper' / 'make device-mapper_install'.
Here's the implementation:
struct dm_task *dm_task_create(int type)
{
struct dm_task *dmt = dm_zalloc(sizeof(*dmt));
if (!dmt) {
log_error("dm_task_create: malloc(%" PRIsize_t ") failed",
sizeof(*dmt));
return NULL;
}
if (!dm_check_version()) {
dm_free(dmt);
return_NULL;
}
dmt->type = type;
dmt->minor = -1;
dmt->major = -1;
dmt->allow_default_major_fallback = 1;
dmt->uid = DM_DEVICE_UID;
dmt->gid = DM_DEVICE_GID;
dmt->mode = DM_DEVICE_MODE;
dmt->no_open_count = 0;
dmt->read_ahead = DM_READ_AHEAD_AUTO;
dmt->read_ahead_flags = 0;
dmt->event_nr = 0;
dmt->cookie_set = 0;
dmt->query_inactive_table = 0;
dmt->new_uuid = 0;
dmt->secure_data = 0;
return dmt;
}