I'm now studying proc file system. I now know that read_proc_t function is called when the proofs file is read, and so for write_proc_t function when the proofs file is written to. But I also find the file_operaitons* field in the definition of proc_dir_entry, and this example code (http://linux.die.net/lkmpg/x810.html).
So I'm confused that what would happen if I provide both implementations of read_proc_t function and the read function in file_operations structure? Which has the precedence over the other? Could one be overwritten by the other? Thanks very much.
When you register proc-entry, proc_register() checks if you specify proc_fops. If you don't, it will set default file operations for procfs. Default operations calls your proc_read and proc_write. So, if you specify proc_fops by yourself, proc_read and proc_write members will not be called.
In linux-3.10 there aren't such things as write_proc_t and read_proc_t. proc_dir_entry has no members read_proc and write_proc. Instead, only proc_fops is used.
Related
What's the usual best practice to split up a really long match on an enum with dozens of variants to handle, each with dozens or hundreds of lines of code?
I've started to create helper functions for each case and just call those functions passing in the enum's fields (or whatever they're called). But it seems a bit redundant to have MyEnum::MyCase{a,b,c} => handle_mycase(a,b,c) many times.
And if that is the best practice, is it possible to destructure MyEnum::MyCase directly in that helper function's parameters, despite the fact that technically it's refutable, since realistically I already know I'm calling it with the right case?
Maybe the crate enum_dispatch helps you.
IIRC, on a high level: It assumes that all your enum variants implement a trait with a function handle_mycase. Then handle_mycase can be called on the enum directly and will be dispatched to the concrete struct.
The Effective go has following advice on naming of getters:
Go doesn't provide automatic support for getters and setters. There's
nothing wrong with providing getters and setters yourself, and it's
often appropriate to do so, but it's neither idiomatic nor necessary
to put Get into the getter's name. If you have a field called owner
(lower case, unexported), the getter method should be called Owner
(upper case, exported), not GetOwner. The use of upper-case names for
export provides the hook to discriminate the field from the method. A
setter function, if needed, will likely be called SetOwner. Both names
read well in practice:
Source: https://golang.org/doc/effective_go.html#Getters
Now, this advice doesn't seem to consistent as the stdlib itself violates this multiple times.
As you can see in above screenshot, there are multiple methods which use GetX naming convention which is advised against in the effective go guide.
So the question is is the advice given in guide wrong or these methods are named wrongly & would be fixed in future versions?
These names are not consistent with Go naming by design. Rob Pike, one of the Go creators, says this about the names in the OS package:
There are inconsistencies but this is the key point. It should be Stdout not StdOut, because that name is coming from the underlying system. Similarly it's Fprintf not FPrintf or FPrintF because that is a very familiar name. These names are coming into Go, not being created there, and the initial cap is the admission fee.
The names will not be changed in a future version of Go.
[go-nuts] FunctionName caseinconsistencies
A lot of the all lowercase names were chosen before we had really
figured out what the naming conventions should be. The rule we
adopted, which might be worth revisiting later, was that entry points
in package os or syscall, which are named after equivalents in C, just
had a single capital at the beginning, to avoid needing to decide
where the internal capitalizations are in abbreviations like geteuid
or getwd or chdir. Names like Readdirnames, which are actual words,
might be worth revisiting at some point.
Russ
os: inconsistent casing in names #1187
Is there any sort of rule about the casing of functions used in the
"os" package? Looking through, it doesn't sound like it's very easy
to recall whether a given function should be called LikeThat or
Likethat.
For instance:
Mkdir
MkdirAll
TempDir
Getenv
ForkExec
Readlink
ReadAt
Readdir
It feels very ad-hoc, and hard to recall.
It's a known issue. It's unplanned.
The term "getters" refers to methods on structs that allow you to read values of (often unexported) fields on that struct. The functions you're pointing to are top-level functions which allow you to read values from the OS. That idiomatic rule is not relevant to this case.
I have some code which depends on some include files which are partly defined at the start of source files (which is usual) and others which are used within functions.
I typical example for that are the OpenFOAM solver sources.
Because the scheme of this code is highly procedural, but I want to put all this into a class which provides init(), run() and maybe release(), I plan to put some of the variables into the classes as private making them members.
I don't want to modify the included files because they belong to a library.
The reason for using a class is that other routines classes run together with this code.
Here is the thing. init() must prepare some variable and there situations that theses variables (being type of other clases) not explicit constructors and special arguments. It is called once. run() is called several times. The procedural code has a loop only and the contents of that loop are put into the run() method.
So the best solution was to put these variables into std::unique_ptr and init can construct whatever it needs to. Obviously with that trick the variable signature changed, so I created a second declaration of a reference like this:
std::unique_ptr<volScalarField> mp_p;
volScalarField &p = *mp_p;
Now this is a bit tedious so I created a macro
FOAMPTR(volVectorField, p)
which does all the work for me:
#define FOAMPTR(TYPE,NAME) std::unique_ptr<TYPE> mp_##NAME; TYPE &NAME=*mp_##NAME
It works pretty well, but I'm not fan of macros in general, especially if you need to debug code.
Now my question is: Is there a better way to tackle this and use something else like a template definition which might do all the magic?
Edit: With 'works pretty well' I mean, that the compiler can translate that. The reference though still is invalid.
Edit: Okay, I solved the invalid pointer problem using two Macros:
#define FOAMPTR(TYPE,NAME) std::unique_ptr<TYPE> mp_##NAME
#define FETCHFOAMREF(NAME) auto &NAME=*mp_##NAME
Now I put FOAMPTR(TYPE,NAME) to the member and I get my unique ptrs. In the run() method the second macro FETCHFOAMREF(NAME) is used. Of course init() must be sure to correctly initialize the object or else the program is going to crash.
I still leave the question open because I'm not satisfied with that solution.
I had browsed internet, but hadn't found an answer.
Previously we used static linking using def file.
Currently this approach is not suitable, because there are cases when dll is not accessible.
So now we need to load dynamically function with unlimited function arguments.
Is there a common approach? Just push in right direction or some topic related for that is OK.
GetProcAddress does not care about the number of arguments the function has. If you use C++ and your problem is name mangling, you can either mark the functions with extern "C" or pass the mangled name to GetProcAddress.
How is it that certain System calls take pointers to structs as arguments? If these structs are defined in the kernel, then how can user programs create instances of them?
There is no magic here. The struct types used in syscalls and meant to be user-createable are declared in header files, just as the syscalls themselves are. Take stat(2):
int stat(const char *path, struct stat *buf);
You get the declaration of struct stat (on Linux) by including sys/stat.h.
Some types are not meant to be directly declared by client code, however. In comments you mentioned semaphores, and sem_t is an example of such. The user header provides only an incomplete declaration, so you can't create an instance directly. This is intentional. In those cases there will be a call that creates an instance and returns a pointer to it, for example:
sem_t *sem_open(const char *name, int oflag);
You are expected to provide that same pointer as an argument to subsequent syscalls, even though you can't dereference it yourself (because its declaration is incomplete). The distinction between structs and struct pointers is extremely important here.
Every time , when you create a new structure inside the kernel , it can be exported to userspace by executing "make headers_install".
So if the user space binary is built in the same machine , it would be having identical copy of the header files(typically in /usr/include).Hence system calls can specify pointers to structures as parameters.