It is known that memory allocation with new calls respective type constructor and memory allocation with malloc does not. But what about kmalloc?
I am trying to develop some system calls and I need to assign memory to a structure below.
struct mailbox{
unsigned long existing_messages;
unsigned long mxid;
struct message *msg;
struct message *last_node;
mailbox(){
existing_messages = 0;
mxid = 0;
msg = NULL;
last_node = NULL;
}
};
If I allocate memory with kmalloc will it call constructor for struct mailbox at allocation time? if not what are the reasonable possible ways to get the constructor called except calling constructor explicitly. Is there any equivalent function as new for memory allocation in kernel?
kmalloc doesn't call constructor.
one way in C++ is to call "placement new".
example:
void* ptr = malloc( sizeof(T) );
T* p = new (ptr) T(); //construct object in memory
note:
you need to call destructor explicitly to avoid memory leaks in object itself,
and then call corresponding de-allocation routine for this memory.
p->~T(); //call destructor
free(ptr); //free memory
Related
I am trying to understand the nvme linux drivers. I am now tackling the function nvme_user_submit_cmd, which I report partially here:
static int nvme_submit_user_cmd(struct request_queue *q,
struct nvme_command *cmd, void __user *ubuffer,
unsigned bufflen, void __user *meta_buffer, unsigned meta_len,
u32 meta_seed, u32 *result, unsigned timeout)
{
bool write = nvme_is_write(cmd);
struct nvme_ns *ns = q->queuedata;
struct gendisk *disk = ns ? ns->disk : NULL;
struct request *req;
struct bio *bio = NULL;
void *meta = NULL;
int ret;
req = nvme_alloc_request(q, cmd, 0, NVME_QID_ANY);
[...]
if (ubuffer && bufflen) {
ret = blk_rq_map_user(q, req, NULL, ubuffer, bufflen,
GFP_KERNEL);
[...]
The ubufferis a pointer to some data in the virtual address space (since this comes from an ioctl command from a user application).
Following blk_rq_map_user I was expecting some sort of mmap mechanism to translate the userspace address into a physical address, but I can't wrap my head around what the function is doing. For reference here's the call chain:
blk_rq_map_user -> import_single_range -> blk_rq_map_user_iov
Following those function just created some more confusion for me and I'd like some help.
The reason I think that this function is doing a sort of mmap is (apart from the name) that this address will be part of the struct request in the struct request queue, which will eventually be processed by the NVME disk driver (https://lwn.net/Articles/738449/) and my guess is that the disk wants the physical address when fulfilling the requests.
However I don't understand how is this mapping done.
ubuffer is a user virtual address, which means it can only be used in the context of a user process, which it is when submit is called. To use that buffer after this call ends, it has to be mapped to one or more physical addresses for the bios/bvecs. The unmap call frees the mapping after the I/O completes. If the device can't directly address the user buffer due to hardware constraints then a bounce buffer will be mapped and a copy of the data will be made.
Edit: note that unless a copy is needed, there is no kernel virtual address mapped to the buffer because the kernel never needs to touch the data.
I am trying to allocate memory in the Linux kernel using kmalloc. I have a structure designed as below:
struct st_fetch_point {
struct sk_buff *end_pkt ;
struct sk_buff *start_pkt ;
struct sk_buff *current_pkt ;
struct st_fetch_point *next_fortp ;
struct st_fetch_point *next_consec ;
};
I have created a new structure of the type st_fetch_point and trying to allocate memory & assign values to the member pointers in below fashion:
struct st_fetch_point *first_fetch_point;
first_fetch_point = kmalloc((sizeof(struct st_fetch_point)), GFP_ATOMIC);
if (!first_fetch_point)
return -ENOMEM;
skb = tcp_send_head(meta_sk);
first_fetch_point->start_pkt = skb;
first_fetch_point->current_pkt = skb;
first_fetch_point->end_pkt = NULL;
first_fetch_point->next_fortp = NULL;
first_fetch_point->next_consec = NULL;
But it looks like the kernel is freezing each time it comes to kmalloc() execution line. I am working on ubuntu 14.04 and really in a fix. I checked syslog and kernlog files and did not find any unusual messages related to the freezing. Is this any issue with the kmalloc() allocation method ?
I'm trying to develop a new syscall for the linux kernel. This syscall will write info on the user buffer that is taken as argument, e.g.:
asmlinkage int new_syscall(..., char *buffer,...){...}
In user space this buffer is statically allocated as:
char buffer[10000];
There's a way (as sizeof() in the user level) to know the whole buffer size (10000 in this case)?
I have tried strlen_user(buffer) but it returns me the length of the string that is currently into the buffer, so if the buffer is empty it returns 0.
You can try passing structure which will contain the buffer pointer & the size of the buffer. But the same structure should also be defined in both user-space application & inside your system-call's code in kernel.
struct new_struct
{
void *p; //set this pointer to your buffer...
int size;
};
//from user-application...
int main()
{
....
struct new_struct req_kernel;
your_system_call_function(...,(void *)&req_kernel,...);
}
........................................................................................
//this is inside your kernel...
your_system_call(...,char __user optval,...)
{
.....
struct new_struct req;
if (copy_from_user(&req, optval, sizeof(req)))
return -EFAULT;
//now you have the address or pointer & size of the buffer
//which you want in kernel with struct req...
}
I'm slightly puzzled by the lack of documentation on the issue, so I may be completely off track here:
When I allocate memory in order to return an object through an unique pointer whose value I have modified, what allocater should I use?
The documentation says that I can provide MIDL_user_allocate() and MIDL_user_free() and the stub will use these -- however that does not make sense in CLSCTX_INPROC_SERVER, as the calling object would need to use (and hence resolve) my allocater.
So, how should I allocate memory here, so that the stub code can properly free the list if the DLL is loaded into SVCHOST, and applications can still use the DLL directly if they so desire.
idl:
HRESULT GetItems([out] DWORD *count, [out, size_is(,count)] ITEM **items);
cpp:
HRESULT STDMETHODCALLTYPE impl::GetBuffer(DWORD *count, ITEM **items)
{
*count = 0;
*items = reinterpret_cast<ITEM *>(/* ??? */);
if(!*items)
return E_OUTOFMEMORY;
*count = 5;
/* fill in items */
return S_OK;
}
From here:
Out-parameters must be allocated by the one called; they are freed by the caller using the standard COM task memory allocator.
where COM task memory allocator is either the set of IMalloc methods or the set of CoTaskMemAlloc()/CoTaskMemRealloc()/CoTaskMemFree() functions that provide the same functionality.
The midl_user-*() functions you mention are used for RPC memory management. You need them in case you deal with RPC interfaces, not COM interfaces.
Visual C++ debug runtime library features so-called allocation hooks. Works this way: you define a callback and call _CrtSetAllocHook() to set that callback. Now every time a memory allocation/deallocation/reallocation is done CRT calls that callback and passes a handful of parameters.
I successfully used an allocation hook to find a reproduceable memory leak - basically CRT reported that there was an unfreed block with allocation number N (N was the same on every program run) at program termination and so I wrote the following in my hook:
int MyAllocHook( int allocType, void* userData, size_t size, int blockType,
long requestNumber, const unsigned char* filename, int lineNumber)
{
if( requestNumber == TheNumberReported ) {
Sleep( 0 );// a line to put breakpoint on
}
return TRUE;
}
since the leak was reported with the very same allocation number every time I could just put a breakpoint inside the if-statement and wait until it was hit and then inspect the call stack.
What other useful things can I do using allocation hooks?
You could also use it to find unreproducible memory leaks:
Make a data structure where you map the allocated pointer to additional information
In the allocation hook you could query the current call stack (StackWalk function) and store the call stack in the data structure
In the de-allocation hook, remove the call stack information for that allocation
At the end of your application, loop over the data structure and report all call stacks. These are the places where memory was allocated but not freed.
The value "requestNumber" is not passed on to the function when deallocating (MS VS 2008). Without this number you cannot keep track of your allocation. However, you can peek into the heap header and extract that value from there:
Note: This is compiler dependent and may change without notice/ warning by the compiler.
// This struct is a copy of the heap header used by MS VS 2008.
// This information is prepending each allocated memory object in debug mode.
struct MsVS_CrtMemBlockHeader {
MsVS_CrtMemBlockHeader * _next;
MsVS_CrtMemBlockHeader * _prev;
char * _szFilename;
int _nLine;
int _nDataSize;
int _nBlockUse;
long _lRequest;
char _gap[4];
};
int MyAllocHook(..) { // same as in question
if(nAllocType == _HOOK_FREE) {
// requestNumber isn't passed on to the Hook on free.
// However in the heap header this value is stored.
size_t headerSize = sizeof(MsVS_CrtMemBlockHeader);
MsVS_CrtMemBlockHeader* pHead;
size_t ptr = (size_t) pvData - headerSize;
pHead = (MsVS_CrtMemBlockHeader*) (ptr);
long requestNumber = pHead->_lRequest;
// Do what you like to keep track of this allocation.
}
}
You could keep record of every allocation request then remove it once the deallocation is invoked, for instance: This could help you tracking memory leak problems that are way much worse than this to track down.
Just the first idea that comes to my mind...