The mmap man pages indicate that closing a file does not result in unmapping of pages. However, I wonder if the following sequence is valid that by the time the read occurs the pages have likely not have been faulted into memory. In other words, is the file still open after the close ? Also is the behavior expected on both Android and iOS?
void func()
{
auto fd = open("test.txt", O_RDONLY);
void *ptr = mmap(nullptr, 16384, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
uint8_t *p = (uint8_t *)ptr;
// Read from *p
}
Related
I am trying to use grub in order to get the memory map, instead of going through the bios route. The problem is that grub seems to be giving me very weird values for some reason. Can anyone help with this?
Relevant code:
This is how I parse the mmap
void mm_init(mmap_entry_t *mmap_addr, uint32_t length)
{
mmap = mmap_addr;
/* Loop through mmap */
printk("-- Scanning memory map --");
for (size_t i = 0; mmap < (mmap_addr + length); i++) {
/* RAM is available! */
if (mmap->type == 1) {
uint64_t starting_addr = (((uint64_t) mmap->base_addr_high) << 32) | ((uint64_t) mmap->base_addr_low);
uint64_t length = (((uint64_t) mmap->length_high) << 32) | ((uint64_t) mmap->length_low);
printk("Found segment starting from 0x%x, with a length of %i", starting_addr, length);
}
/* Next entry */
mmap = (mmap_entry_t *) ((uint32_t) mmap + mmap->size + sizeof(mmap->size));
}
}
This is my mmap_entry_t struct (not the one in multiboot.h):
struct mmap_entry {
uint32_t size;
uint32_t base_addr_low, base_addr_high;
uint32_t length_low, length_high;
uint8_t type;
} __attribute__((packed));
typedef struct mmap_entry mmap_entry_t;
And this is how I call mm_init()
/* Kernel main function */
void kmain(multiboot_info_t *info)
{
/* Check if grub can give us a memory map */
/* TODO: Detect manually */
if (!(info->flags & (1<<6))) {
panic("couldn't get memory map!");
}
/* Init mm */
mm_init((mmap_entry_t *) info->mmap_addr, info->mmap_length);
for(;;);
}
This is the output I get on qemu:
-- Scanning memory map --
Found segment starting from 0x0, with a length of 0
Found segment starting from 0x100000, with a length of 0
And yes, I am pushing eax and ebx before calling kmain. Any ideas on what is going wrong here?
It turns out that the bit masking stuff was the problem. If we drop that, we can still have 32-bit addresses and the memory map works just fine.
I have some problem in using QLocalServer/QLocalSocket.
I'm sending raw pixel data from server to client, and there is a huge memory leakage while process. but I couldn't know what is the reason...
Memory increases about 20MB/1sec (when I checked with my eyes in system administrator.)
Followings are my codes.
Server
void qsharedServer::updateImageData(unsigned char* r_data, int r_width, int r_height, int r_step, int r_label_i){
QLocalSocket* connection = 0;
connection = clientSocket;
if (connection)
{
if (connection->isOpen())
{
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_7);
const char* rc_data = reinterpret_cast<const char*>(r_data);
out <<r_step*r_height<< r_width << r_height << r_step;
out.writeBytes(rc_data, r_step*r_height);
connection->write(block);
connection->flush();
}
}
Client
void qsharedClient::readSocket(){
QByteArray block = connection->readAll();
QDataStream in(&block, QIODevice::ReadOnly);
in.setVersion(QDataStream::Qt_5_7);
/* Read Raw Data */
char* data;
uint size;
int width;
int height;
int step;
while (!in.atEnd())
{
in >> size >> width >> height >> step;
in.readBytes(data, size);
}
emit drawData((unsigned char*)data, width, height, step);
}
These two codes can communicate well, but memories are increasing very sharply and terminated when it over certain level.
I tried like connection->reset() or QByteArray::clear()..etc but it doesn't worked.
Is there any idea with my problem??
How about using QTcpServer/QTcpSocket?? This can solve my problem??
Please share your idea. Thanks!!
This should be happening because named pipe stores all data until you close it.
As a solution you should call disconnectFromServer() for socket (on the sender or receiver side - does not matter) once you have sent/received enough data for one packet.
Working with some Core Audio code written before 64-bit processors were introduced in iOS. The app compiles and runs fine on 32 bit processors, but when I try an run on an iPhone 5s, I get two compiler errors.
AQRecorderState ars;
static void AQInputCallback(void *aqRecorderState, // AQRecorderState struct
AudioQueueRef inQ,
AudioQueueBufferRef inBuffer,
const AudioTimeStamp *timestamp,
unsigned long inNumPackets,
const AudioStreamPacketDescription *mDataFormat){
AQRecorderState *pArs = (AQRecorderState *)aqRecorderState;
if (inNumPackets == 0 && pArs->mDataFormat.mBytesPerPacket != 0)
inNumPackets = inBuffer->mAudioDataByteSize / pArs->mDataFormat.mBytesPerPacket;
// This line returns an error "No matching function call for 'AudioFileWritePackets'"
if (AudioFileWritePackets(pArs->mAudioFile,
false,
inBuffer->mAudioDataByteSize,
mDataFormat,
pArs->mCurrentPacket,
&inNumPackets,
inBuffer->mAudioData) == noErr){
pArs->mCurrentPacket += inNumPackets; // advance packet index pointer
}
// don't re-queue the sound buffers if stop has been pressed
if (!pArs->mIsRunning)
return;
// send the buffer back to the queue for more data
AudioQueueEnqueueBuffer(pArs->mQueue, inBuffer, 0, NULL);
}
Getting the same error when trying to create a new Audio Queue. I believe it's because of the AQInputCallback line...
// Error: No matching function for call to 'AudioQueueNewInput'
AudioQueueNewInput(&ars.mDataFormat,
AQInputCallback,
&ars,
NULL,
kCFRunLoopCommonModes,
0,
&ars.mQueue);
Thanks for your help! I've read through the Learning Core Audio book multiple times and searched SO and the internet for days trying to figure this out.
The first error is likely due to inNumPackets, which is defined as unsigned long. In a 32-bit process long is 32 bits whereas in a 64 bit process long is 64 bits. The parameter in AudioFileWritePackets expects a UInt32*. You can the long to and from a temp variable to make the call:
UInt32 inNumPacketsTmp = inNumPackets;
if (AudioFileWritePackets(pArs->mAudioFile,
false,
inBuffer->mAudioDataByteSize,
mDataFormat,
pArs->mCurrentPacket,
&inNumPacketsTemp,
inBuffer->mAudioData) == noErr){
inNumPackets = inNumPacketsTmp;
pArs->mCurrentPacket += inNumPackets; // advance packet index pointer
}
I'm not sure about the second one.
I read all I could find about memory management in the Tcl API, but haven't been able to solve my problem so far. I wrote a Tcl extension to access an existing application. It works, except for a serious issue: memory leak.
I tried to reproduce the problem with minimal code, which you can find at the end of the post. The extension defines a new command, recordings, in namespace vtcl. The recordings command creates a list of 10000 elements, each element being a new command. Each command has data attached to it, which is the name of a recording. The name subcommand of each command returns the name of the recording.
I run the following Tcl code with tclsh to reproduce the problem:
load libvtcl.so
for {set ii 0} {$ii < 1000} {incr ii} {
set recs [vtcl::recordings]
foreach r $recs {rename $r ""}
}
The line foreach r $recs {rename $r ""} deletes all the commands at each iteration, which frees the memory of the piece of data attached to each command (I can see that in gdb). I can also see in gdb that the reference count of variable recs goes to 0 at each iteration so that the contents of the list is freed. Nonetheless, I see the memory of the process running tclsh going up at each iteration.
I have no more idea what else I could try. Help will be greatly appreciated.
#include <stdio.h>
#include <string.h>
#include <tcl.h>
static void DecrementRefCount(ClientData cd);
static int ListRecordingsCmd(ClientData cd, Tcl_Interp *interp, int objc,
Tcl_Obj *CONST objv[]);
static int RecordingCmd(ClientData cd, Tcl_Interp *interp, int objc,
Tcl_Obj *CONST objv[]);
static void
DecrementRefCount(ClientData cd)
{
Tcl_Obj *obj = (Tcl_Obj *) cd;
Tcl_DecrRefCount(obj);
return;
}
static int
ListRecordingsCmd(ClientData cd, Tcl_Interp *interp, int objc,
Tcl_Obj *CONST objv[])
{
char name_buf[20];
Tcl_Obj *rec_list = Tcl_NewListObj(0, NULL);
for (int ii = 0; ii < 10000; ii++)
{
static int obj_id = 0;
Tcl_Obj *cmd;
Tcl_Obj *rec_name;
cmd = Tcl_NewStringObj ("rec", -1);
Tcl_AppendObjToObj (cmd, Tcl_NewIntObj (obj_id++));
rec_name = Tcl_NewStringObj ("DM", -1);
snprintf(name_buf, sizeof(name_buf), "%04d", ii);
Tcl_AppendStringsToObj(rec_name, name_buf, (char *) NULL);
Tcl_IncrRefCount(rec_name);
Tcl_CreateObjCommand (interp, Tcl_GetString (cmd), RecordingCmd,
(ClientData) rec_name, DecrementRefCount);
Tcl_ListObjAppendElement (interp, rec_list, cmd);
}
Tcl_SetObjResult (interp, rec_list);
return TCL_OK;
}
static int
RecordingCmd(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{
Tcl_Obj *rec_name = (Tcl_Obj *)cd;
char *subcmd;
subcmd = Tcl_GetString (objv[1]);
if (strcmp (subcmd, "name") == 0)
{
Tcl_SetObjResult (interp, rec_name);
}
else
{
Tcl_Obj *result = Tcl_NewStringObj ("", 0);
Tcl_AppendStringsToObj (result,
"bad command \"",
Tcl_GetString (objv[1]),
"\"",
(char *) NULL);
Tcl_SetObjResult (interp, result);
return TCL_ERROR;
}
return TCL_OK;
}
int
Vtcl_Init(Tcl_Interp *interp)
{
#ifdef USE_TCL_STUBS
if (Tcl_InitStubs(interp, "8.5", 0) == NULL) {
return TCL_ERROR;
}
#endif
if (Tcl_PkgProvide(interp, "vtcl", "0.0.1") != TCL_OK)
return TCL_ERROR;
Tcl_CreateNamespace(interp, "vtcl", (ClientData) NULL,
(Tcl_NamespaceDeleteProc *) NULL);
Tcl_CreateObjCommand(interp, "::vtcl::recordings", ListRecordingsCmd,
(ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
return TCL_OK;
}
The management of the Tcl_Obj * reference counts looks absolutely correct, but I do wonder whether you're freeing all the other resources associated with a particular instance in your real code. It might also be something else entirely; your code is not the only thing in Tcl that allocates memory! Furthermore, the default memory allocator in Tcl does not actually return memory to the OS, but instead holds onto it until the process ends. Figuring out what is wrong can be tricky.
You can try doing a build of Tcl with the --enable-symbols=mem passed to configure. That makes Tcl build in an extra command, memory, which allows more extensive checking of memory management behaviour (it also does things like ensure that memory is never written to after it is freed). It's not enabled by default because it has a substantial performance hit, but it could well help you track down what's going on. (The memory info subcommand is where to get started.)
You could also try adding -DPURIFY to the CFLAGS when building; it completely disables the Tcl memory allocator (so memory checking tools like — commercial — Purify and — OSS — Electric Fence can get accurate information, instead of getting very confused by Tcl's high-performance thread-aware allocator) and may allow you to figure out what is going on.
I found where the leak is. In function ListRecordingsCmd, I replaced line
Tcl_AppendObjToObj (cmd, Tcl_NewIntObj (obj_id++));
with
Tcl_Obj *obj = Tcl_NewIntObj (obj_id++);
Tcl_AppendObjToObj (cmd, obj);
Tcl_DecrRefCount(obj);
The memory allocated to store the object id was not released. The memory used by the tclsh process is now stable.
I am basically looking to create Memory (RAM) optimization function as given in following applications. (For iPhone sdk)
https://itunes.apple.com/us/app/memory-100-pro/id644853504?mt=8
https://itunes.apple.com/th/app/memory-pro/id483447668?mt=8
This function basically kills third party app background process to achieve the same.
Can any one guide me that how can I find that particular process is not system process and kill the process.
I am using following code to get list of process with process id.
struct kinfo_proc *procs = NULL, *newprocs;
char thiscmd[MAXCOMLEN + 1];
pid_t thispid;
int mib[4];
size_t miblen;
int i, st, nprocs;
size_t size;
size = 0;
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_ALL;
mib[3] = 0;
miblen = 3;
st = sysctl(mib, miblen, NULL, &size, NULL, 0);
do {
size += size / 10;
newprocs = realloc(procs, size);
if (newprocs == 0) {
if (procs)
free(procs);
errx(1, "could not reallocate memory");
}
procs = newprocs;
st = sysctl(mib, miblen, procs, &size, NULL, 0);
} while (st == -1 && errno == ENOMEM);
nprocs = size / sizeof(struct kinfo_proc);
/* Now print out the data */
for (i = 0; i < nprocs; i++) {
thispid = procs[i].kp_proc.p_pid;
strncpy(thiscmd, procs[i].kp_proc.p_comm, MAXCOMLEN);
thiscmd[MAXCOMLEN] = '\0';
printf("%d\t%s\n", thispid, thiscmd);
NSString * processName = [[NSString alloc] initWithFormat:#"%s", procs[i].kp_proc.p_comm];
if([processName isEqualToString:#"templerunbrave"])
kill(thispid, SIGKILL);
}
/* Clean up */
free(procs);
A 3rd party app is sandboxed and does not have the power or authority to arbitrarily kill processes and threads that do not belong to it.
The way these "memory" apps work is by manually allocating memory incrementally in a for loop until they get memory warnings, then manually freeing the memory. Because the OS does not know that your memory is not being used in the app, it takes active memory away from other apps, sometimes even force closing them in order to provide their memory resources to your app. Once you manually free the memory, this memory that was allocated to your app is now available to the whole system, but the other apps which were killed or in deep sleep will remain killed or in deep sleep.