parent */ /* * read address from my child and waits that he terminates */ read (com_pipe[0], &kernel_addr, sizeof(kernel_addr)); wait (&status); printf("kernel starts at: %p\n", kernel_addr); } else /* I'm the child */ { close (com_pipe[0]); /* communication child --> parent */ /* * seek the start address of the kernel */ seek_ska ( (char*) &argc); } return 0; } [allowsmilie] => 1 [showsignature] => 0 [ipaddress] => [iconid] => 0 [visible] => 1 [attach] => 0 [infraction] => 0 [reportthreadid] => 0 [isusenetpost] => 1 [msgid] => <3e0374e6.0308290128.3477f550@posting.google.com> [ref] => <3F4C5888.2ED7867D@hotmail.com> <3e0374e6.0308271316.4f968c26@posting.google.com> <3F4D9212.73095649@hotmail.com> <3F4DC925.C0AE4527@hotmail.com> <3F4DDCA8.E4ED2862@hotmail.com> <3e0374e6.0308281403.1eacc41f@posting.google.com> <3F4EC904.5915F840@hotmail.com> [htmlstate] => on_nl2br [postusername] => Loic [ip] => loic-dev@gmx.ne [isdeleted] => 0 [usergroupid] => [membergroupids] => [displaygroupid] => [password] => [passworddate] => [email] => [styleid] => [parentemail] => [homepage] => [icq] => [aim] => [yahoo] => [msn] => [skype] => [showvbcode] => [showbirthday] => [usertitle] => [customtitle] => [joindate] => [daysprune] => [lastvisit] => [lastactivity] => [lastpost] => [lastpostid] => [posts] => [reputation] => [reputationlevelid] => [timezoneoffset] => [pmpopup] => [avatarid] => [avatarrevision] => [profilepicrevision] => [sigpicrevision] => [options] => [akvbghsfs_optionsfield] => [birthday] => [birthday_search] => [maxposts] => [startofweek] => [referrerid] => [languageid] => [emailstamp] => [threadedmode] => [autosubscribe] => [pmtotal] => [pmunread] => [salt] => [ipoints] => [infractions] => [warnings] => [infractiongroupids] => [infractiongroupid] => [adminoptions] => [profilevisits] => [friendcount] => [friendreqcount] => [vmunreadcount] => [vmmoderatedcount] => [socgroupinvitecount] => [socgroupreqcount] => [pcunreadcount] => [pcmoderatedcount] => [gmmoderatedcount] => [assetposthash] => [fbuserid] => [fbjoindate] => [fbname] => [logintype] => [fbaccesstoken] => [newrepcount] => [vbseo_likes_in] => [vbseo_likes_out] => [vbseo_likes_unread] => [temp] => [field1] => [field2] => [field3] => [field4] => [field5] => [subfolders] => [pmfolders] => [buddylist] => [ignorelist] => [signature] => [searchprefs] => [rank] => [icontitle] => [iconpath] => [avatarpath] => [hascustomavatar] => 0 [avatardateline] => [avwidth] => [avheight] => [edit_userid] => [edit_username] => [edit_dateline] => [edit_reason] => [hashistory] => [pagetext_html] => [hasimages] => [signatureparsed] => [sighasimages] => [sigpic] => [sigpicdateline] => [sigpicwidth] => [sigpicheight] => [postcount] => 11 [islastshown] => [isfirstshown] => [attachments] => [allattachments] => ) --> parent */ > > /* > * read address from my child and waits that he terminates > */ > read (com_pipe[0], &kernel_addr, sizeof(kernel_addr)); > wait (&status); > > printf("kernel starts at: %p\n", kernel_addr); > } > else /* I'm the child */ > { > close (com_pipe[0]); /* communication child --> parent */ > > /* > * seek the start address of the kernel > */ > seek_ska ( (char*) &argc); > } > > return 0; > }[/ref] Thanks Loic, It works on my Linux and Solaris machine. On ,HP-UX 11.00 it gives following message: Pid 18834 received a SIGSEGV for stack growth failure. Possible causes: insufficient memory or swap space, or stack size exceeded maxssiz. kernel starts at: 00000000 Manish [allowsmilie] => 1 [showsignature] => 0 [ipaddress] => [iconid] => 0 [visible] => 1 [attach] => 0 [infraction] => 0 [reportthreadid] => 0 [isusenetpost] => 1 [msgid] => <3F50381F.FB489037@hotmail.com> [ref] => <3F4C5888.2ED7867D@hotmail.com> <3e0374e6.0308271316.4f968c26@posting.google.com> <3F4D9212.73095649@hotmail.com> <3F4DC925.C0AE4527@hotmail.com> <3F4DDCA8.E4ED2862@hotmail.com> <3e0374e6.0308281403.1eacc41f@posting.google.com> <3F4EC904.5915F840@hotmail.com> <3e0374e6.0308290128.3477f550@posting.google.com> [htmlstate] => on_nl2br [postusername] => Manish [ip] => manishbaronia@h [isdeleted] => 0 [usergroupid] => [membergroupids] => [displaygroupid] => [password] => [passworddate] => [email] => [styleid] => [parentemail] => [homepage] => [icq] => [aim] => [yahoo] => [msn] => [skype] => [showvbcode] => [showbirthday] => [usertitle] => [customtitle] => [joindate] => [daysprune] => [lastvisit] => [lastactivity] => [lastpost] => [lastpostid] => [posts] => [reputation] => [reputationlevelid] => [timezoneoffset] => [pmpopup] => [avatarid] => [avatarrevision] => [profilepicrevision] => [sigpicrevision] => [options] => [akvbghsfs_optionsfield] => [birthday] => [birthday_search] => [maxposts] => [startofweek] => [referrerid] => [languageid] => [emailstamp] => [threadedmode] => [autosubscribe] => [pmtotal] => [pmunread] => [salt] => [ipoints] => [infractions] => [warnings] => [infractiongroupids] => [infractiongroupid] => [adminoptions] => [profilevisits] => [friendcount] => [friendreqcount] => [vmunreadcount] => [vmmoderatedcount] => [socgroupinvitecount] => [socgroupreqcount] => [pcunreadcount] => [pcmoderatedcount] => [gmmoderatedcount] => [assetposthash] => [fbuserid] => [fbjoindate] => [fbname] => [logintype] => [fbaccesstoken] => [newrepcount] => [vbseo_likes_in] => [vbseo_likes_out] => [vbseo_likes_unread] => [temp] => [field1] => [field2] => [field3] => [field4] => [field5] => [subfolders] => [pmfolders] => [buddylist] => [ignorelist] => [signature] => [searchprefs] => [rank] => [icontitle] => [iconpath] => [avatarpath] => [hascustomavatar] => 0 [avatardateline] => [avwidth] => [avheight] => [edit_userid] => [edit_username] => [edit_dateline] => [edit_reason] => [hashistory] => [pagetext_html] => [hasimages] => [signatureparsed] => [sighasimages] => [sigpic] => [sigpicdateline] => [sigpicwidth] => [sigpicheight] => [postcount] => 12 [islastshown] => [isfirstshown] => [attachments] => [allattachments] => ) --> 4GB VM for 32 bit processes - UNIX Programming

4GB VM for 32 bit processes - UNIX Programming

Hi Experts, I have a question regarding the limit of resource (VM), a process can cosume on 32bit unix (SunOS 5.7, Red Hat Linux 7.2, AIX 4.3, HP-UX 11.00) machines. Let us assume that Physical+Swap memory on these systems is > 4GB. Theoretically, can a process consume 4GB of VM (private + shared) on all these machines, or is there any limit imposed by these systems which can not be overcome even by changing kernel parameters ? I am asking this question, because somewhere, I read that linux has a limitation of 3GB, while HP 2GB. I assume, these limits ...

  1. #1

    Default 4GB VM for 32 bit processes

    Hi Experts,
    I have a question regarding the limit of resource (VM), a process
    can cosume on 32bit unix (SunOS 5.7, Red Hat Linux 7.2, AIX 4.3, HP-UX
    11.00) machines.
    Let us assume that Physical+Swap memory on these systems is > 4GB.
    Theoretically, can a process consume 4GB of VM (private + shared) on all
    these machines, or is there any limit imposed by these systems which
    can not be overcome even by changing kernel parameters ?

    I am asking this question, because somewhere, I read that linux has a
    limitation of 3GB, while HP 2GB. I assume, these limits are of private
    memory. With shared memory (mmap) this should go till 4 GB. Do I get it
    correct?
    Manish

    Manish Guest

  2. #2

    Default Re: 4GB VM for 32 bit processes

    Manish Baronia <com> writes:
     

    There are some limits, often depending on hardware limitations.
    The traditional Unix kernel maps the VM the kernel uses in each
    user address space; the only protection is the fact that the PROT_USER
    bit is not set. When a syscall is done, the kernel can access both
    user and kernel data easily (though copyin()/copyout() are needed to
    fend off page faults)

    On older Solaris/SPARC this was generally around .25 or .5 of a GB
    (the larger the system, the more kernel memory was needed so the smaller
    the user segment got)

    With UltraSPARC the kernel got its own context and a completely different
    context is used for the kernel; this frees up to VM needed for the kernel.
    To simplify some algorithms, VM on UltraSPARC is limited to 4GB-4MB
    for 32 bit processes; i.e., 3.996 GB, very close to the theoretical max.

    Casper
    --
    Expressed in this posting are my opinions. They are in no way related
    to opinions held by my employer, Sun Microsystems.
    Statements on Sun products included here are not gospel and may
    be fiction rather than truth.
    Casper Guest

  3. #3

    Default Re: 4GB VM for 32 bit processes

    Hi Manish,

    I'm not an expert, but I will attempt to answer some of your
    questions.
     

    Obviously, max. 4GB ;-)

     

    Certainly, the amount of VM available to a process is limited by the
    ulimit. But this can be eventually 'adjusted' on-the-fly.

    However, as explained by Casper, the 4G are often divided into two
    areas: user-space and kernel-space. For instance, on Linux, a 3G-1G
    splitting is common. Some Un*x systems go e.g. for a 2G-2G splitting.

    On Linux, this splitting can be configured. But it requires that you
    re-compile the kernel (this is, in a sense, a kernel parameter. But
    you can't change it "on the fly").

     

    Assuming a default config, even if theoritically 3G are available on
    Linux, you will probably be able to mmap only 2G approximatively (the
    process itself, of course, needs also VM for the text and data!). The
    reason is that the 3G are further divided into two areas: 1G for the
    heap, and 2G for "the rest". I don't know how these last splitting can
    be configured...


    What's about PAE, which can address 64G? Linux 2.6.0 (beta) offers the
    possibility to have a 4G-4G mapping for the user-space / kernel-space
    (again, you need to compile the kernel with that option enabled).
    However, I still believe that the 1G for the heap remains, so in that
    case you will be able to mmap() only 3G max.

    The workaround to use more VM on PAE, is to fork several instances of
    the process and use some IPC. That's definitively not so easy as with
    a linear addressing, but remember that we hit the 32 bits hard limit
    here. So we can't expect miracles...

    My answers are definitively Linux centric, but some of the material
    provided should also apply to other Un*x systems. Of course, on 64
    bits arch, all these problems vanish...


    BTW, a final comment. You can easily write a small program that does
    nothing but mmap chunks of memory (eg 1M) until it fails. That way,
    you know the amount of VM available for shared memory on your system.
    For instance, one my Linux box (standard 3G-1G splitting), I'm able to
    mmap 2,046 M (the 0.002 M are for text and data of the program
    itself).


    Regards,
    Loic.
    Loic Guest

  4. #4

    Default Re: 4GB VM for 32 bit processes

    Loic Domaigne wrote: 

    I don't know about Linux, but on some Unix systems this
    can give a false result. Under some cirstances Solaris will
    surround each mmap'ed area with guard pages: chunks of virtual
    memory not mapped to any physical memory (to help catch runaway
    pointers and the like). Also, under some cirstances Solaris
    imposes alignment requirements on the mmap'ed regions. The
    upshot is that all those 1MB areas might not be contiguous.

    A reasonable countermeasure would be to run Loic's test
    several times, with different chunk sizes: 1MB, 2MB, 4MB and
    so on until mmap() starts to fail after only a few chunks.
    Calculate the apparent total VM at each chunk size and see
    if the results are nearly constant or seem to be rising
    toward an asymptote. Examination of the addresses of the
    successive allocated areas might also be illuminating.

    --
    com
    Eric Guest

  5. #5

    Default Re: 4GB VM for 32 bit processes

    Loic Domaigne wrote:
     
    >
    > Obviously, max. 4GB ;-)

    >
    > Certainly, the amount of VM available to a process is limited by the
    > ulimit. But this can be eventually 'adjusted' on-the-fly.
    >
    > However, as explained by Casper, the 4G are often divided into two
    > areas: user-space and kernel-space. For instance, on Linux, a 3G-1G
    > splitting is common. Some Un*x systems go e.g. for a 2G-2G splitting.
    >
    > On Linux, this splitting can be configured. But it requires that you
    > re-compile the kernel (this is, in a sense, a kernel parameter. But
    > you can't change it "on the fly").

    >
    > Assuming a default config, even if theoritically 3G are available on
    > Linux, you will probably be able to mmap only 2G approximatively (the
    > process itself, of course, needs also VM for the text and data!). The
    > reason is that the 3G are further divided into two areas: 1G for the
    > heap, and 2G for "the rest". I don't know how these last splitting can
    > be configured...
    >
    >
    > What's about PAE, which can address 64G? Linux 2.6.0 (beta) offers the
    > possibility to have a 4G-4G mapping for the user-space / kernel-space
    > (again, you need to compile the kernel with that option enabled).
    > However, I still believe that the 1G for the heap remains, so in that
    > case you will be able to mmap() only 3G max.
    >
    > The workaround to use more VM on PAE, is to fork several instances of
    > the process and use some IPC. That's definitively not so easy as with
    > a linear addressing, but remember that we hit the 32 bits hard limit
    > here. So we can't expect miracles...
    >
    > My answers are definitively Linux centric, but some of the material
    > provided should also apply to other Un*x systems. Of course, on 64
    > bits arch, all these problems vanish...
    >
    > BTW, a final comment. You can easily write a small program that does
    > nothing but mmap chunks of memory (eg 1M) until it fails. That way,
    > you know the amount of VM available for shared memory on your system.
    > For instance, one my Linux box (standard 3G-1G splitting), I'm able to
    > mmap 2,046 M (the 0.002 M are for text and data of the program
    > itself).
    >
    > Regards,
    > Loic.[/ref]

    Thanks Jerry, Casper, Loic, Eric,
    The answers do give me insight of memory management. Does
    getrlimit(RLIMIT_AS, &rlimit) ; rlimit.rlim_max returns me correct user
    area value(According to kernel parameters)?
    Thamks,
    Manish

    Manish Guest

  6. #6

    Default Re: 4GB VM for 32 bit processes

    Hi!
     

    You're welcome!
     

    If you mean e.g. that the user-space/kernel-space splitting is token into
    account, I doubt! Indeed RLIM_INFINITY could be returned. I'm not sure if
    the meaning of RLIM_INFINITY is the same on all implementations.

    For instance, on Linux, you can get RLIM_INFINITY, although the answer is
    really 3G assuming a 3G-1G splitting. I don't know if that particular
    getrlimit() implementation is conform to SUS, but I would think so.


    Cheers,
    Loic.

    --
    Article posté via l'accès Usenet http://www.mes-news.com
    Accès par Nnrp ou Web
    Loic Guest

  7. #7

    Default Re: 4GB VM for 32 bit processes

    Loic Domaigne wrote:
     
    >
    > You're welcome!

    >
    > If you mean e.g. that the user-space/kernel-space splitting is token into
    > account, I doubt! Indeed RLIM_INFINITY could be returned. I'm not sure if
    > the meaning of RLIM_INFINITY is the same on all implementations.
    >
    > For instance, on Linux, you can get RLIM_INFINITY, although the answer is
    > really 3G assuming a 3G-1G splitting. I don't know if that particular
    > getrlimit() implementation is conform to SUS, but I would think so.
    >
    > Cheers,
    > Loic.
    >
    > --
    > Article posté via l'accès Usenet http://www.mes-news.com
    > Accès par Nnrp ou Web[/ref]

    So, which C function can return me this 3G value?


    Manish Guest

  8. #8

    Default Re: 4GB VM for 32 bit processes


    "Manish Baronia" <com> wrote in message
    news:com...
     

    There is no function that gives you the information you want. For one
    thing, fragmentation may mean that even though you could map 3Gb in smaller
    pieces, you can't map a single 3Gb piece. You're going to have to give us a
    lot more information if you want help:

    1) What platform(s) are you particularly interested in?

    2) Exactly what information are you looking for?

    3) What do you plan to do with it?

    DS


    David Guest

  9. #9

    Default Re: 4GB VM for 32 bit processes

    David Schwartz wrote:
     
    >
    > There is no function that gives you the information you want. For one
    > thing, fragmentation may mean that even though you could map 3Gb in smaller
    > pieces, you can't map a single 3Gb piece. You're going to have to give us a
    > lot more information if you want help:
    >
    > 1) What platform(s) are you particularly interested in?
    >
    > 2) Exactly what information are you looking for?
    >
    > 3) What do you plan to do with it?
    >
    > DS[/ref]

    Hello David,
    Let me tell you why I need this information:
    We are making an application, which runs on SunOS 5.7, Red Hat Linux 7.2, AIX
    4.3, HP-UX
    11.00 machines.
    This applications runs on big designs and works for several hours (depending
    on the size and complexity of design). This application does two passes on
    these designs. First pass is very thin, in this pass, it collects information
    about the design, and second pass is costly one where it does the actual
    operations.
    Depending on the information collected from first pass it predicts VM
    requirements in costly second pass.
    Then, depending on the values obtained from getrlimit, it gives various
    messages to user, if the VM (private or total is less than what is predicted
    for costly second pass).
    My application uses malloc and mmap (Shared) both, so it can grow in private
    and shared area both.
    Why I am interested in knowing 4GB limit is, I want to know if I can warn user
    to shift to 64bit machines
    if this limit is hit. But here lies the dilemma, because if Linux can only
    support 3GB for user space (ie. my malloc and mmap can only grow upto 3GB), I
    should give this warning if > 3GB VM requirements is predicted in first pass.

    That is why I am interested in knowing these limits.
    I hope I am clear in explaining it.
    Thanks,
    Manish


    Manish Guest

  10. #10

    Default Re: 4GB VM for 32 bit processes

    Hi Manish,

    If you are interested:

    I've some code that allows you to determine *automatically* at which
    address the kernel starts. The code assumes that the user-space starts
    at adresse 0x00000000 up to kernel_addr-1, and the kernel space starts
    at kernel_addr up to max_addr (i.e. 0xffffffff on 32 bits arch).
    Furthermore, it assumes that the stacks grows towards lower addresses.

    If those conditions are met (which is e.g. the case on Linux/IA32),
    then the program shall computes automatically the value of
    kernel_addr, determining that way the user-space/kernel-space
    splitting.

    Regards,
    Loic.
    Loic Guest

  11. #11

    Default Re: 4GB VM for 32 bit processes

    > Hello Loic, 

    Ok, here we go. This code is "best effort", I provide no guarantee or
    whatsoever! If someone has a simpler solution or see possible
    improvements etc., please let me know :-)

    Thanks,
    Loic.

    --- code begins here-----------------------------------------------------------

    /************************************************** *********************
    * Copyright (c) 2003, Loic Domaigne <net>
    * All right reserved.
    *
    * This code is licensed under BSD License. See:
    * http://www.opensource.org/licenses/bsd-license.php
    *
    ************************************************** **********************

    This program computes the address at which the kernel space starts
    It uses the memory layout specific to Linux.

    Notes:

    1- The is no error checks. But serious code should verifies that
    the syscalls succeeded.

    2- This program should work on any 32 bits Un*x with the following
    memory layout. BUT THIS DOESN'T HAVE BEEN TESTED!

    +---------------------+ 0xffffffff
    | | ^
    | kernel space
    | | v
    +=====================+ kernel_addr
    | process env | ^
    +---------------------+ |
    | argc | |
    +---------------------+ |
    | argv | |
    +---------------------+ | user space
    | | | |
    | v | |
    stack growth |
    |
    | | |
    | | v
    +---------------------+ 0x00000000

    3- Using symmetry, one can easily adapt this code for system where
    the kernel start at address 0x00000000 to kernel_addr, and where the
    stack growths towards higher addresses.

    */

    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <unistd.h>
    #include <sys/wait.h>

    int com_pipe[2]; /* pipe used between child and parent */
    char* p; /* pointer to "climb" the stack */


    /************************************************** ******************/
    /* sigsegv_handler. SIGSEGV handler */
    /************************************************** ******************/
    /* */
    /* This handler is call when we touch the first byte of the kernel */
    /* address. It writes to the pipe the corresponding address and */
    /* terminates the child. */
    /************************************************** ******************/
    void
    sigsegv_handler(int signo)
    {
    /*
    * both write() and _exit() are async-signal-safe!
    */
    write (com_pipe[1], &p, sizeof(p));
    _exit (0);
    }


    /************************************************** ******************/
    /* sigsegv_handler. seek start address of the kernel */
    /************************************************** ******************/
    /* */
    /* This function seeks the start address of the kernel, by */
    /* "climbing up" the process environment parameters stored in the */
    /* stack. */
    /* */
    /* It starts to seek at address addr_argc, which is the address of */
    /* the argc parameter of the main() routine, and looks char by char */
    /* if the next address still belongs to the process. */
    /* */
    /* At a given address, a SIGSEGV will be generated: this is exactly */
    /* where the kernel starts. In order to return that address for */
    /* further use, the program caught SIGSEGV by installing the */
    /* handler sigsegv. */
    /************************************************** ******************/
    void
    seek_ska (char *addr_argc /* address of the argc argument */
    )
    {
    struct sigaction new_action; /* our new action upon SIGSEGV */
    char c; /* use to dereference p */

    /*
    * install new action to catch SIGSEGV
    */
    new_action.sa_handler = sigsegv_handler;
    new_action.sa_flags = 0;
    sigemptyset (&new_action.sa_mask);
    sigaction (SIGSEGV, &new_action, NULL);

    /*
    * "climbs up" the stack until SIGSEGV is generated
    */
    for (p=addr_argc; p; p++)
    {
    c = *p; /* try to access p */
    }

    /* we never go here! */
    }


    /************************************************** ******************/
    /* main entry point */
    /************************************************** ******************/
    int
    main(int argc,
    char *argv[]
    )
    {
    pid_t child_pid; /* pid of the child */
    void* kernel_addr; /* the kernel starts at that address */

    /*
    * create pipe and fork
    */
    pipe (com_pipe);
    child_pid = fork();

    if (child_pid) /* I'm the parent */
    {
    int status; /* status of my chlid */

    close (com_pipe[1]); /* communication child --> parent */

    /*
    * read address from my child and waits that he terminates
    */
    read (com_pipe[0], &kernel_addr, sizeof(kernel_addr));
    wait (&status);

    printf("kernel starts at: %p\n", kernel_addr);
    }
    else /* I'm the child */
    {
    close (com_pipe[0]); /* communication child --> parent */

    /*
    * seek the start address of the kernel
    */
    seek_ska ( (char*) &argc);
    }

    return 0;
    }
    Loic Guest

  12. #12

    Default Re: 4GB VM for 32 bit processes

    Loic Domaigne wrote:
     
    >
    > Ok, here we go. This code is "best effort", I provide no guarantee or
    > whatsoever! If someone has a simpler solution or see possible
    > improvements etc., please let me know :-)
    >
    > Thanks,
    > Loic.
    >
    > --- code begins here-----------------------------------------------------------
    >
    > /************************************************** *********************
    > * Copyright (c) 2003, Loic Domaigne <net>
    > * All right reserved.
    > *
    > * This code is licensed under BSD License. See:
    > * http://www.opensource.org/licenses/bsd-license.php
    > *
    > ************************************************** **********************
    >
    > This program computes the address at which the kernel space starts
    > It uses the memory layout specific to Linux.
    >
    > Notes:
    >
    > 1- The is no error checks. But serious code should verifies that
    > the syscalls succeeded.
    >
    > 2- This program should work on any 32 bits Un*x with the following
    > memory layout. BUT THIS DOESN'T HAVE BEEN TESTED!
    >
    > +---------------------+ 0xffffffff
    > | | ^
    > | kernel space
    > | | v
    > +=====================+ kernel_addr
    > | process env | ^
    > +---------------------+ |
    > | argc | |
    > +---------------------+ |
    > | argv | |
    > +---------------------+ | user space
    > | | | |
    > | v | |
    > stack growth |
    > |
    > | | |
    > | | v
    > +---------------------+ 0x00000000
    >
    > 3- Using symmetry, one can easily adapt this code for system where
    > the kernel start at address 0x00000000 to kernel_addr, and where the
    > stack growths towards higher addresses.
    >
    > */
    >
    > #include <stdio.h>
    > #include <stdlib.h>
    > #include <signal.h>
    > #include <unistd.h>
    > #include <sys/wait.h>
    >
    > int com_pipe[2]; /* pipe used between child and parent */
    > char* p; /* pointer to "climb" the stack */
    >
    > /************************************************** ******************/
    > /* sigsegv_handler. SIGSEGV handler */
    > /************************************************** ******************/
    > /* */
    > /* This handler is call when we touch the first byte of the kernel */
    > /* address. It writes to the pipe the corresponding address and */
    > /* terminates the child. */
    > /************************************************** ******************/
    > void
    > sigsegv_handler(int signo)
    > {
    > /*
    > * both write() and _exit() are async-signal-safe!
    > */
    > write (com_pipe[1], &p, sizeof(p));
    > _exit (0);
    > }
    >
    > /************************************************** ******************/
    > /* sigsegv_handler. seek start address of the kernel */
    > /************************************************** ******************/
    > /* */
    > /* This function seeks the start address of the kernel, by */
    > /* "climbing up" the process environment parameters stored in the */
    > /* stack. */
    > /* */
    > /* It starts to seek at address addr_argc, which is the address of */
    > /* the argc parameter of the main() routine, and looks char by char */
    > /* if the next address still belongs to the process. */
    > /* */
    > /* At a given address, a SIGSEGV will be generated: this is exactly */
    > /* where the kernel starts. In order to return that address for */
    > /* further use, the program caught SIGSEGV by installing the */
    > /* handler sigsegv. */
    > /************************************************** ******************/
    > void
    > seek_ska (char *addr_argc /* address of the argc argument */
    > )
    > {
    > struct sigaction new_action; /* our new action upon SIGSEGV */
    > char c; /* use to dereference p */
    >
    > /*
    > * install new action to catch SIGSEGV
    > */
    > new_action.sa_handler = sigsegv_handler;
    > new_action.sa_flags = 0;
    > sigemptyset (&new_action.sa_mask);
    > sigaction (SIGSEGV, &new_action, NULL);
    >
    > /*
    > * "climbs up" the stack until SIGSEGV is generated
    > */
    > for (p=addr_argc; p; p++)
    > {
    > c = *p; /* try to access p */
    > }
    >
    > /* we never go here! */
    > }
    >
    > /************************************************** ******************/
    > /* main entry point */
    > /************************************************** ******************/
    > int
    > main(int argc,
    > char *argv[]
    > )
    > {
    > pid_t child_pid; /* pid of the child */
    > void* kernel_addr; /* the kernel starts at that address */
    >
    > /*
    > * create pipe and fork
    > */
    > pipe (com_pipe);
    > child_pid = fork();
    >
    > if (child_pid) /* I'm the parent */
    > {
    > int status; /* status of my chlid */
    >
    > close (com_pipe[1]); /* communication child --> parent */
    >
    > /*
    > * read address from my child and waits that he terminates
    > */
    > read (com_pipe[0], &kernel_addr, sizeof(kernel_addr));
    > wait (&status);
    >
    > printf("kernel starts at: %p\n", kernel_addr);
    > }
    > else /* I'm the child */
    > {
    > close (com_pipe[0]); /* communication child --> parent */
    >
    > /*
    > * seek the start address of the kernel
    > */
    > seek_ska ( (char*) &argc);
    > }
    >
    > return 0;
    > }[/ref]

    Thanks Loic,
    It works on my Linux and Solaris machine. On ,HP-UX 11.00 it gives following
    message:

    Pid 18834 received a SIGSEGV for stack growth failure.
    Possible causes: insufficient memory or swap space,
    or stack size exceeded maxssiz.
    kernel starts at: 00000000

    Manish


    Manish Guest

  13. #13

    Default Re: 4GB VM for 32 bit processes

    Hi Manish,
     

    Well, I told you that the program makes strong assumptions about the
    memory layout. It works on Linux, but I don't know about other Un*x
    implementations. Unfortunately, I don't have access to a HP-UX, so I
    can't tell you what's wrong.

    You should check what memory model HP-UX implements, and change the
    code accordingly. The first think I would check is whether HP-UX
    implements the symmetric-version of the memory model supported by the
    original code (i.e. kernel starts at address 0x00000000 up to
    user_space and stack growths towards higher addresses).

    BTW. If you port the code to HP-UX, it would be nice that you make the
    changes public! I think, this might also interest other people.


    Regards,
    Loic.
    Loic Guest

  14. #14

    Default Re: 4GB VM for 32 bit processes

    Loic Domaigne wrote:
     
    >
    > Well, I told you that the program makes strong assumptions about the
    > memory layout. It works on Linux, but I don't know about other Un*x
    > implementations. Unfortunately, I don't have access to a HP-UX, so I
    > can't tell you what's wrong.
    >
    > You should check what memory model HP-UX implements, and change the
    > code accordingly. The first think I would check is whether HP-UX
    > implements the symmetric-version of the memory model supported by the
    > original code (i.e. kernel starts at address 0x00000000 up to
    > user_space and stack growths towards higher addresses).
    >
    > BTW. If you port the code to HP-UX, it would be nice that you make the
    > changes public! I think, this might also interest other people.
    >
    > Regards,
    > Loic.[/ref]

    Hello Loic,
    Optimized build in Linux is not giving me correct value for kernel start
    address. Do you know the reason?
    Manish

    Manish Guest

  15. #15

    Default Re: 4GB VM for 32 bit processes

    In article <google.com>,
    net (Loic Domaigne) writes: 
    >
    > Well, I told you that the program makes strong assumptions about the
    > memory layout. It works on Linux, but I don't know about other Un*x
    > implementations. Unfortunately, I don't have access to a HP-UX, so I
    > can't tell you what's wrong.[/ref]

    HP-UX's stack grows in the opposite direction to just about everything
    else I've seen. I don't know the HP-UX memory layout though, and I no
    longer have access to any HP-UX machines.

    --
    Andrew Gabriel
    Consultant Software Engineer
    Andrew Guest

  16. #16

    Default Re: 4GB VM for 32 bit processes

    Hi Manish!
     

    That's clear why. The keypoint of the program is the loop:

    /*
    * "climbs up" the stack until SIGSEGV is generated
    */
    for (p=addr_argc; p; p++)
    {
    c = *p; /* try to access p */
    }

    which generates a SIGSEGV when the kernel start address is reached. However,
    notice that the dereference of p (or equivalently the variable c), is never
    re-used.

    So if you optimize, gcc might get right of the instruction c=*p, thinking it
    is useless... Which is definitively not the case for that particular
    program!

    The corresponding assembler output for the loop (compiled with -O3) seems to
    confirm that point:

    ..L50:
    incl %eax
    testl %eax, %eax
    jne .L50
    xorl %ecx, %ecx
    movl %ecx, p


    Regards,
    Loic.
    --
    Article posté via l'accès Usenet http://www.mes-news.com
    Accès par Nnrp ou Web
    Loic Guest

  17. #17

    Default Re: 4GB VM for 32 bit processes

    Manish Baronia wrote:
     
    > >
    > > Well, I told you that the program makes strong assumptions about the
    > > memory layout. It works on Linux, but I don't know about other Un*x
    > > implementations. Unfortunately, I don't have access to a HP-UX, so I
    > > can't tell you what's wrong.
    > >
    > > You should check what memory model HP-UX implements, and change the
    > > code accordingly. The first think I would check is whether HP-UX
    > > implements the symmetric-version of the memory model supported by the
    > > original code (i.e. kernel starts at address 0x00000000 up to
    > > user_space and stack growths towards higher addresses).
    > >
    > > BTW. If you port the code to HP-UX, it would be nice that you make the
    > > changes public! I think, this might also interest other people.
    > >
    > > Regards,
    > > Loic.[/ref]
    >
    > Hello Loic,
    > Optimized build in Linux is not giving me correct value for kernel start
    > address. Do you know the reason?
    > Manish[/ref]

    Some more experiments show that , in optimized builds, accessing kernel address
    contents do not throw seg faults, its only when I change the content of (*p = '/0'),
    SEG fault comes on Linux and HP. This is strange.
    This behaviour is seen only in optimized build, In normal debug build, even accessing
    content of kernel addresses (c =*p) throws SEG faults.
    Manish

    Manish Guest

  18. #18

    Default Re: 4GB VM for 32 bit processes

    > > Optimized build in Linux is not giving me correct value for kernel start [/ref]
     

    No it isn't... Unless I missed something ;-)
    See my previous post, where I explain that if you optimize the code,
    you might get ride of the instruction "c=*p". And as a result, no
    SIGSEGV is generated...

    Oh yes... One thing: do not change the content of *p. If you do that, you
    smash the whole environment variables passed to the program. Depending
    how you have integrate that code in your software, you might get some
    unexpected surprises!!

    Regards,
    Loic.

    --
    Article posté via l'accès Usenet http://www.mes-news.com
    Accès par Nnrp ou Web
    Loic Guest

  19. #19

    Default Re: 4GB VM for 32 bit processes

    Loic Domaigne wrote:
     
    >
    > That's clear why. The keypoint of the program is the loop:
    >
    > /*
    > * "climbs up" the stack until SIGSEGV is generated
    > */
    > for (p=addr_argc; p; p++)
    > {
    > c = *p; /* try to access p */
    > }
    >
    > which generates a SIGSEGV when the kernel start address is reached. However,
    > notice that the dereference of p (or equivalently the variable c), is never
    > re-used.
    >
    > So if you optimize, gcc might get right of the instruction c=*p, thinking it
    > is useless... Which is definitively not the case for that particular
    > program!
    >
    > The corresponding assembler output for the loop (compiled with -O3) seems to
    > confirm that point:
    >
    > .L50:
    > incl %eax
    > testl %eax, %eax
    > jne .L50
    > xorl %ecx, %ecx
    > movl %ecx, p
    >
    > Regards,
    > Loic.
    > --
    > Article posté via l'accès Usenet http://www.mes-news.com
    > Accès par Nnrp ou Web[/ref]

    Yes, That's correct. I have changed
    "void seek_ska (char *addr_argc /* address of the argc argument */ )" to
    "char seek_ska (char *addr_argc /* address of the argc argument * )"
    And, in the end I am returning "c". This avoids optimizer removing the
    statement, and it works fine.

    Also, for HP, as Andrew has told that the stack grows in opposite direction, I
    have changed following:
    " for (p=addr_argc; p; p++)" to :
    " for (p=addr_argc; p; p--)"
    And it is working fine on my HP machines. If anybody finds any problems in
    this, please let me know.
    Thanks,
    Manish


    Manish Guest

  20. #20

    Default Re: 4GB VM for 32 bit processes

    Hi Manish,
     [/ref]
     

    clever...

     

    Yes... actually, I didn't thought about it. But I believe, you can
    automatically find out in which direction does the stack grow.

    Indeed, ISTM that 'comparing' the value of the address of
    argc and argv (for instance) should be enough...

     

    I see a problem here!! IIRC, the memory layout of HP-UX is quite different
    from the other Un*x I saw...

    You must understand that this program find the first invalid address
    'after' the program's stack. It doesn't mean necessarily that it is the
    start address of the kernel (it happens to be the case on Linux/IA, but
    Linux/IA is a PARTICULAR implementation).

    Again, the 2 strong assumptions of my solution are:

    - the VM is divided into 2 contiguous parts: one for the user space, and one
    for the kernel space.

    - the kernel starts right 'after' the process stack.

    If one if this assumption doesn't hold for any reason, the address that
    you are obtaining is wrong.


    I would definitively check the validity of such assumptions on the
    corresponding NG for the Unix implementations you are interested
    (e.g. comp.unix.solaris for Solaris, or comp.sys.hpux for HP-UX).


    Good luck!
    Loic.
    --
    Article posté via l'accès Usenet http://www.mes-news.com
    Accès par Nnrp ou Web
    Loic Guest

Page 1 of 2 12 LastLast

Similar Threads

  1. # of Coldfusion processes
    By neostructuralist in forum Coldfusion Server Administration
    Replies: 1
    Last Post: September 22nd, 07:31 AM
  2. Timing several processes
    By Anthony Akens in forum PERL Beginners
    Replies: 13
    Last Post: December 4th, 02:00 PM
  3. child processes
    By Vikas Vijay in forum UNIX Programming
    Replies: 2
    Last Post: July 24th, 09:22 AM
  4. Unkillable processes?
    By Bradley M Alexander in forum Debian
    Replies: 6
    Last Post: July 17th, 07:20 PM
  5. Kproc Processes
    By Janis in forum AIX
    Replies: 0
    Last Post: July 2nd, 06:47 PM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •