0

The idea behind this program is to simply access the ram and download the data from it to a txt file. Later Ill convert the txt file to jpeg and hopefully it will be readable . However when I try and read from the RAM using NEW[] it takes waaaaaay to long to actually copy all the values into the file? Isnt it suppose to be really fast? I mean I save pictures everyday and it doesn't even take a second? Is there some other method I can use to dump memory to a file?

#include <stdio.h>
#include <stdlib.h>
#include <hw/pci.h>
#include <hw/inout.h>
#include <sys/mman.h>


main()
{
    FILE *fp;
    fp = fopen ("test.txt","w+d");
    int NumberOfPciCards = 3;
    struct pci_dev_info info[NumberOfPciCards];
    void *PciDeviceHandler1,*PciDeviceHandler2,*PciDeviceHandler3;
    uint32_t *Buffer;
    int *BusNumb;   //int Buffer;
    uint32_t counter =0;
    int i;
    int r;
    int y;
    volatile uint32_t *NEW,*NEW2;
    uintptr_t iobase;
    volatile uint32_t *regbase;

    NEW = (uint32_t *)malloc(sizeof(uint32_t));
    NEW2 = (uint32_t *)malloc(sizeof(uint32_t));
    Buffer = (uint32_t *)malloc(sizeof(uint32_t));
    BusNumb = (int*)malloc(sizeof(int));
    printf ("\n 1");

    for (r=0;r<NumberOfPciCards;r++)
    {
        memset(&info[r], 0, sizeof(info[r]));
    }

    printf ("\n 2");

        //Here the attach takes place.
    for (r=0;r<NumberOfPciCards;r++)
    {
        (pci_attach(r) < 0) ? FuncPrint(1,r) : FuncPrint(0,r);
    }

    printf ("\n 3");

    info[0].VendorId = 0x8086;  //Wont be using this one
    info[0].DeviceId = 0x3582;   //Or this one
    info[1].VendorId = 0x10B5;   //WIll only be using this one PLX 9054 chip
    info[1].DeviceId = 0x9054;   //Also PLX 9054
    info[2].VendorId = 0x8086;   //Not used
    info[2].DeviceId = 0x24cb;    //Not used

    printf ("\n 4");

        //I attached the device and give it a handler and set some setting.
    if ((PciDeviceHandler1 = pci_attach_device(0,PCI_SHARE|PCI_INIT_ALL, 0, &info[1])) == 0)
                {
                    perror("pci_attach_device fail");
                    exit(EXIT_FAILURE);
                }

            for (i = 0; i < 6; i++)
            //This just prints out some details of the card.    
                                {
                if (info[1].BaseAddressSize[i] > 0)
                    printf("Aperture %d: "
                    "Base 0x%llx Length %d bytes Type %s\n", i,
                    PCI_IS_MEM(info[1].CpuBaseAddress[i]) ? PCI_MEM_ADDR(info[1].CpuBaseAddress[i]) :   PCI_IO_ADDR(info[1].CpuBaseAddress[i]),
                            info[1].BaseAddressSize[i],PCI_IS_MEM(info[1].CpuBaseAddress[i]) ? "MEM" : "IO");
                }
            printf("\nEnd of Device random info dump---\n");


    printf("\nNEWs Address : %d\n",*(int*)NEW);
        //Not sure if this is a legitimate way of memory allocation but I cant see to read the ram any other way.
    NEW = mmap_device_memory(NULL, info[1].BaseAddressSize[3],PROT_READ|PROT_WRITE|PROT_NOCACHE, 0,info[1].CpuBaseAddress[3]);

                 //Here is where things are starting to get messy and REALLY long to just run through all the ram and dump it.
                 //Is there some other way I can dump the data in the ram into a file?
        while (counter!=info[1].BaseAddressSize[3])
        {

            fprintf(fp, "%x",NEW[counter]);
            counter++;
        }

        fclose(fp);

    printf("0x%x",*Buffer);

}
tshepang
  • 12,111
  • 21
  • 91
  • 136
  • 1
    On a modern computer with a modern operating system you *can't* access the RAM. You can access the process *virtual memory* though, but parts of it may not be accessible and the OS will terminate ("crash") your program if you try to access those pages. – Some programmer dude Jul 18 '14 at 10:20
  • 1
    Also note that the process virtual memory can be up to 4GB on a 32-bit system, and way way more on a 64-bit machine. A big image is maybe at most a couple of MB, that's a factor of 1000 smaller than the memory space on a 32-bit system. – Some programmer dude Jul 18 '14 at 10:22
  • 1
    Hmm, it might also help if you mentioned your system specifics. For example, is this on QNX? – thkala Jul 18 '14 at 10:38
  • What's the purpose of calling `malloc(sizeof(uint32_t))` and storing the result into `NEW` if you don't use that later (you overwrite the NEW value with what `mmap_device_memory()` returns)...? – CiaPan Jul 18 '14 at 10:50
  • Oh just a relic of some old commented code. I just quickly removed a bunch of unnecessary stuff. – BaddaBoompshhh Jul 18 '14 at 10:53
  • @thkala Yes its is QNX – BaddaBoompshhh Jul 18 '14 at 10:53

2 Answers2

3

A few issues that I can see:

  • You are writing blocks of 4 bytes - that's quite inefficient. The stream buffering in the C library may help with that to a degree, but using larger blocks would still be more efficient.

  • Even worse, you are writing out the memory dump in hexadecimal notation, rather than the bytes themselves. That conversion is very CPU-intensive, not to mention that the size of the output is essentially doubled. You would be better off writing raw binary data using e.g. fwrite().

  • Depending on the specifics of your system (is this on QNX?), reading from I/O-mapped memory may be slower than reading directly from physical memory, especially if your PCI device has to act as a relay. What exactly is it that you are doing?

In any case I would suggest using a profiler to actually find out where your program is spending most of its time. Even a rudimentary system monitor would allow you to determine if your program is CPU-bound or I/O-bound.

As it is, "waaaaaay to long" is hardly a valid measurement. How much data is being copied? How long does it take? Where is the output file located?

P.S.: I also have some concerns w.r.t. what you are trying to do, but that is slightly off-topic for this question...

thkala
  • 84,049
  • 23
  • 157
  • 201
  • Do you know QNX? I cant find ANY QNX support what so ever so if you could help that that would be amazing !It seems like you really know what you are talking about. THis is what im trying to do. I have an FPGA on a board that stores data directly into memory using a PLX9054. Now I want to come from CPU side using the PLX chip to access that piece of memory so that I can process/store etc. The thing is the data is RAW so if you said that my output method changes the data then that cant be good at all : / . – BaddaBoompshhh Jul 18 '14 at 10:47
  • How would you recommend writing out the data in bytes and in format? – BaddaBoompshhh Jul 18 '14 at 11:01
  • If you must dump the raw memory just write them as they are... Do a plain `fwrite` specifying the starting address of the memory you want to dump and the size of the memory block. If later you need to view it as hexadecimal use `hd` or one of the thousands of hex editors you can find. – Matteo Italia Jul 18 '14 at 11:04
  • @user3690127: 1. Sorry, I have no experience on QNX, just general programming experience. 2. So the device acts as a data relay? Or are you manipulating the various MMU tables to access the RAM directly? 3. The best format for memory dumps is raw binary data. Just use `fwrite()` or `write()`... – thkala Jul 18 '14 at 11:07
  • @thkala Well what do you think is best? Wouldnt using it as a Relay just use more processing time? At the moment it looks like manipulation really. But I simply need to extract data from a certain block of ram :/ . My R&D time is limited and PCI drivers isnt easy. – BaddaBoompshhh Jul 18 '14 at 12:21
  • Also... how would I use fwrite() to write out the values with maximum efficiency ? – BaddaBoompshhh Jul 18 '14 at 13:28
  • Thanks allot for the replies ! – BaddaBoompshhh Jul 22 '14 at 07:13
  • @thkala Hey could you please check out this post as well? http://stackoverflow.com/questions/25309068/lubuntu-pci-driver-where-to-start-looking I tried to send you a message but it seems we cant to PMs here. – BaddaBoompshhh Aug 15 '14 at 08:44
1

For fastest speed: write the data in binary form and use the open() / write() / close() API-s. Since your data is already available in a contiguous block of (virtual) memory it is a waste to copy it to a temporary buffer (used by the fwrite(), fprintf(), etc. API-s).

The code using write() will be similar to:

int fd = open("filename.bin", O_RDWR|O_CREAT, S_IRWXU);
write(fd, (void*)NEW, 4*info[1].BaseAddressSize[3]);
close(fd);

You will need to add error handling and make sure that the buffer size is specified correctly.

To reiterate, you get the speed-up from:

  • avoiding the conversion from binary to ASCII (as pointed out by others above)
  • avoiding many calls to libc
  • reducing the number of system-calls (from inside libc)
  • eliminating the overhead of copying data to a temporary buffer inside the fwrite()/fprintf() and related functions (buffering would be useful if your data arrived in small chunks, including the case of converting to ASCII in 4 byte units)

I intentionally ignore commenting on other parts of your code as it is apparently not intended to be production quality yet and your question is focused on how to speed up writing data to a file.

maverick
  • 436
  • 2
  • 10
  • Hey could you please check this post as well ? http://stackoverflow.com/questions/25309068/lubuntu-pci-driver-where-to-start-looking Thanks – BaddaBoompshhh Aug 15 '14 at 08:45