Skip to main content

Migrate your apps from OS/2 to Linux: Part 2. Memory management, IPC, and file handling

Pipes and shared memory

Dinakar Guniguntala (dgunigun-at-in.ibm.com), Staff Software Engineer, IBM, Software Group
Dinakar Guniguntala holds a B.Eng. degree in Computer Engineering from REC Surat. He has been employed with IBM Global Services, India, since February 1998, where he works on operating system internals. He has worked on the OS/2 kernel, graphics engine, and filesytems, as well as on embedded Linux, the Linux kernel, and Linux thread libraries. He can be reached at dgunigun-at-in.ibm.com.
Sathyan Doraiswamy (dsathyan-at-in.ibm.com), Staff Software Engineer, IBM, Software Group
Sathyan Doraiswamy holds a B.Eng. degree in Electronics and Communications from University Visvesvaraya College of Engineering, Bangalore. He joined IBM India in June 1997. He works for Engineering & Technology Services and specializes in firmware for embedded and real time systems. He has vast programming experience on Windows and Linux device drivers and on VxWorks. You can contact him at dsathyan-at-in.ibm.com.
Anand Santhanam (asanthan-at-in.ibm.com), Software Engineer, IBM, Software Group
Anand K. Santhanam has a B.Eng. in Computer Science from Madras University, India. He has been in IBM Global Services (Software Labs), India, since July 1999. He is a member of the Linux Group at IBM, where he has worked with ARM-Linux, character/X-based device drivers, power management in embedded systems, PCI device drivers, and multithreaded programming in Linux. Other areas of interest are OS internals and networking. You can contact him at asanthan-at-in.ibm.com.
Srinivasan Muthuswamy (smuthusw-at-in.ibm.com), Software Engineer, IBM, Software Group
Srinivasan S. Muthuswamy has a B.Eng. in Computer Engineering from the Government College of Technology, Coimbatore, India. He has been in IBM Global Services, India since August 2000. He has worked on multithreaded applications in Linux and on Web applications using WSBCC/Java technologies/Websphere/MQSeries. He has also worked on Crystal Reports and Lotus Domino. You can contact him at smuthusw-at-in.ibm.com.
Rinson Antony (arinson-at-in.ibm.com), Software Engineer, IBM, Software Group
Rinson Antony has a Bachelor of Engineering degree in Computer Engineering from Bombay University, India. He has been in IBM Global Services, India since July 2000. He has worked on multithreaded applications in Linux and Web applications using Java technologies, Websphere, and XML. Other areas of interest are PCI device drivers and networking. You can contact him at arinson-at-in.ibm.com.
Brahmaiah Vallabhaneni (bvallabh-at-in.ibm.com), Software Engineer, IBM, Software Group
Brahmaiah Vallabhaneni has a B.Eng. degree from BITS, Pilani, India. He has been in IBM Global Services, India, since August 2002. He has worked on GNU C Compiler porting, character device drivers, power management in embedded systems, PCI device drivers, and multithreaded programming in Linux. Other areas of interest are Linux internals and networking. You can contact him at bvallabh-at-in.ibm.com.

Summary:  Linux is evolving as the predominant operating system of the new millennium, and legacy operating systems such as OS/2® are being gradually phased out. This series of articles helps the developers involved in the tedious process of migrating/porting the OS/2 system drivers and applications to Linux. In this second of three installments, the authors focus on managing pipes, memory, and files.

Date:  05 May 2004
Level:  Advanced
Activity:  1057 views

Part 1 of this series covered threads and synchronization mechanisms like semaphores and mutexes. This second installment looks closely at memory management, various IPC mechanisms including shared memory and pipes, and file management.

Memory management

OS/2 offers developers a 32-bit, linear (flat) memory address space. It allocates, protects, and manipulates memory in terms of pages.

OS/2 applications allocate and manipulate memory in terms of memory objects, which consist of one or more pages. The smallest memory allocation is one page. But an application can suballocate a memory object in memory blocks whose size can range from 1 byte to the size of the memory object. When an application asks OS/2 to allocate memory, a linear address range is reserved. The range is not backed by physical memory until the memory is committed. Commitment assigns physical memory to the linear address range. An attempt to read from or write to uncommitted memory causes an access violation.

Linux also has a 32-bit flat memory address space. Unlike OS/2, however, each process in Linux sees a different set of linear addresses. Any request to allocate dynamic memory by a process results in a new range of linear addresses becoming a part of its address space. This range of addresses is referred to as a memory region. Allocation of physical memory is deferred to the point where it is actually referenced.

Table 1. Memory management mapping

OS/2LinuxClassification
Allocation
DosAllocMem
DosSetMem
Suballocation
DosAllocMem
DosSubSetMem
DosSubAllocMem
DosSubFreeMem
DosSubUnsetMem
Page-aligned with memory protection
posix_memalign
mprotect
Page-aligned without memory protection
posix_memalign
Non page-aligned without memory protection
malloc/new
Context-specific
DosFreeMem free
delete (if allocated by new)
Mappable
DosAllocSeg malloc/newMappable
DosFreeSeg free/deleteMappable

The Classification column indicates whether the OS/2 construct is mappable or context-specific:

  • Mappable:
    The OS/2 construct can be mapped to the specified Linux construct(s) by closely examining the types, parameters, return codes, and the like. Both the OS/2 and Linux constructs provide similar functionality.
  • Context-specific:
    The given OS/2 construct may or may not have an equivalent construct in Linux, or Linux may have more than one construct that provides similar functionality. In either case, the decision to use a specific Linux construct(s) depends on the application context.

Committing and suballocating memory

In OS/2, the recommended way to manage memory is to make a large memory allocation early in program execution, then to commit or suballocate memory as the need occurs. After the memory object is allocated, the application uses one of two ways to manage the memory object:

  • Commit and decommit the memory as it is required (See Listing 1)
  • Set up the memory object as a heap and suballocate memory from the heap (See Listing 2)

Committing and decommitting memory gives the application more control over the process, but the application will have to keep track of which pages are committed and which are not.

When suballocating memory from a heap, OS/2 keeps track of commitment and decommitment of physical memory pages, which means the application does not have to worry about it.

In Linux, the application need not worry about committing/decomitting and suballocation. The same memory allocation system call (malloc/posix_memalign) can be used for allocating memory of any size. The memory allocator will always return the memory block from the free-list, which best fits the required size. The operating system will take care of committing the allocated memory.

Linux follows an optimistic memory allocation strategy. This means that when malloc() returns non-NULL, there is no guarantee that the memory really is available. In case it turns out that the system is out of memory, one or more processes will be killed by the infamous OOM ("out of memory") killer.

Allocating memory

The system call DosAllocMem() is used in OS/2 to allocate and reserve a range of pages. The memory can be committed during allocation or later by a call to DosSetMem():

APIRET DosAllocMem(PPVOID ppbBase, ULONG size, ULONG attr);
APIRET DosSetMem(PVOID pbBase, ULONG size, ULONG flag);

  • ppbBase points to the pointer to the allocated memory
  • size indicates the requested size in bytes
  • attr is the set of flags describing the allocation attributes and desired access protection
  • flag is a set of flags specifying commitment or decommitment, and desired access protection

A committed page has its access controlled by an access protection attribute. These protection attributes are read protection (PAG_READ), write protection (PAG_WRITE), execute protection (PAG_EXECUTE), and guard page protection (PAG_GUARD). Note that memory allocated by DosAllocMem is always page-aligned and cannot be resized.

If an application wants to use suballocation, it must first allocate memory by using DosAllocMem() and then set up the memory for suballocation by calling DosSubSetMem(). The application can then use DosSubAllocMem() to allocate sections of the heap and the DosSubFreeMem() function to release the memory. DosSubUnSetMem() ends the use of memory set up for suballocation:

APIRET DosSubSetMem(PVOID pbBase, ULONG flag, ULONG size);
APIRET DosSubAllocMem(PVOID pbBase, PPVOID ppMemblock, ULONG size);
APIRET DosSubFreeMem(PVOID pbBase, PVOID pOffset, ULONG size);
APIRET DosSubUnsetMem(PVOID pbBase);

  • pbBase points to the memory already allocated by DosAllocMem()
  • size is the size in bytes
  • ppMemblock is the pointer to a pointer to the memory block that will be allocated by DosSubAllocMem()
  • pOffset is the pointer to the memory block that will be freed by DosSubFreeMem()

In the context of migration, memory allocation in Linux falls into two types: page-aligned and non-page-aligned.

Page-aligned memory allocation with and without memory protection
The system call posix_memalign() can be used to allocate page-aligned memory in Linux. By default, the memory area has PROT_READ | PROT_WRITE. These memory protection attributes can be changed using the call mprotect(). The library function free() can be used to free the memory space allocated by posix_memalign():

int posix_memalign(void **memptr, size_t alignment, size_t size);
int mprotect(const void *addr, size_t size, int prot);

  • *memptr contains the address of the allocated memory. The address of the allocated memory will be a multiple of alignment, which must be a power of two and a multiple of sizeof(void *).
  • addr is the pointer to the allocated memory whose protection flags have to be changed by mprotect().
  • prot are the protection flags and include:
    • PROT_NONE: the memory cannot be accessed at all
    • PROT_READ: the memory can be read
    • PROT_WRITE: the memory can be written to
    • PROT_EXEC: the memory can contain executing code

Non page-aligned memory allocation without memory protection
OS/2, by default, gives a page-aligned memory. If page-aligned memory is not a requirement and the default access protection of PROT_READ | PROT_WRITE is sufficient, then malloc() can be used to allocate memory in Linux, and free() can be used to free the allocated memory:

void *malloc(size_t size)

Alternatively, for applications coded in C++, the keyword new can be used to allocate memory and delete can be used to free the memory space. Make sure that new is used along with the nothrow option so that if there is any error in allocating memory, it does not throw an exception but rather returns a NULL pointer.


Freeing memory

OS/2 uses DosFreeMem() to release a previously allocated memory object from the virtual address space of the subject process:

APIRET DosFreeMem(PVOID pbBase);

Linux uses free() to free the allocated memory:

void free(void *memptr)

Segmented memory allocation

The system call DosAllocSeg() can also be used to allocate memory blocks up to 64K. Use DosMemAvail() to find the amount of available memory that can be allocated, and DosFreeSeg() to free the memory. Parameter size indicates the size in bytes (with a maximum of 64KB), selector is a pointer to an integer to receive the selector, and flags must be zero.

USHORT BLXAPI DosAllocSeg (USHORT size, PSEL selector, USHORT flags)
USHORT BLXAPI DosFreeSeg(SEL selector)

Linux does not provide a segmented memory allocation model.

Examples


Listing 1. OS/2 macro memory management


	//  OS/2 example of memory allocation/de-allocation by committing
   	// and decommitting memory


      APIRET  ulrc;

      PBYTE   pb;


      /* Allocate 16KB object */

      ulrc = DosAllocMem((PVOID *) &pb, 2097152, PAG_READ | PAG_WRITE);


      /* Commit 4KB          */

      ulrc = DosSetMem(pb, 4096, PAG_COMMIT);


      strcpy(pb, "The memory object has just been used.");

      printf("%s\n",pb);


     /* De-Commit 4KB          */

      ulrc = DosSetMem(pb, 4096, PAG_DECOMMIT);


      //Free the memory area

      ulrc = DosFreeMem(pb);


Listing 2. OS/2 micro memory management


	//  OS/2 example of memory suballocation. It sets up 8192 bytes
	// for suballocation and then allocates two small blocks of memory


      APIRET  ulrc;

      PBYTE   pbBase, pb1, pb2;


      /* Allocate 8K object    */

      ulrc = DosAllocMem((PVOID *) &pbBase, 8192, fALLOC);


      /* Set up object or suballocation     */

      ulrc = DosSubSetMem(pbBase, DOSSUB_INIT, 8192);


      /* Suballocate 100 bytes */

      ulrc = DosSubAllocMem(pbBase,(PVOID *) &pb1,100);


      /* Suballocate 500 bytes */

      ulrc = DosSubAllocMem(pbBase,(PVOID *) &pb2,500);


      /* Free 1st suballocation*/
    ulrc = DosSubFreeMem(pbBase, pb1, 100);


      /* Suballocate 50 bytes  */

      ulrc = DosSubAllocMem(pbBase, (PVOID *) &pb1, 50);


      /* Free all suballocation*/
    ulrc = DosSubFreeMem(pbBase, pb1, 50);
    ulrc = DosSubFreeMem(pbBase, pb1, 500);


      /* End the suballocation     */

      ulrc = DosSubUnsetMem(pbBase)


       //Free the memory area
    ulrc = DosFreeMem(pbBase);


Listing 3. OS/2 segments


    SEL
   selector;



    /* Allocate a 4KB block */

    if (DosAllocSeg(4096, &selector, 0) != 0) {

       printf("DosAllocSeg()
   failed\n");

       return
   1;

    }


    // print the allocated memory address

    printf("4 Kb block allocated at :
   %04X\n",selector);


    // Free the memory segment

    if (DosFreeSeg(selector) != 0) {

       printf("DosFreeSeg() failed - selector = %04X\n",
   selector);

       return
   1;

    }


Listing 4. Linux page-aligned memory management


	// Page-aligned memory allocation with memory write protection


   int main (void)

   {

      char**  ppcBuf;                      /* Pointer to memory
   object            */

      int ret = 0;                         /* Return code
            */


      //allocate page-aligned memory area. By default both read and write

     //are allowed. If that's the requirement then no need to use
   mprotect

      ret = posix_memalign(ppcBuf,  4096, 4096);


      //write protect the memory

     ret = mprotect(*ppcBuf, 4096, PROT_READ);


      //Free the memory area

      free(*ppcBuf);


      return 0;

   }


Listing 5. Linux non-page aligned memory management


	// Non page-aligned memory allocation with default memory protection
	// both read and write allowed


   #define USE_MALLOC 1


   char *pcBaseAddress = NULL;


   if (USE_MALLOC == 1) {

       // Allocate memory using malloc

       pcBaseAddress =  (char *) malloc(4096L);

   }

   else {

       // Allocate memory using new

       pcBaseAddress =  new (nothrow) char[4096];

   }

   if (pcBaseAddress == NULL) {

      return 1;

   }

   if (USE_MALLOC == 1) {

       // free the memory space

       free(pcBaseAddress);

   }

   else {

       // free memory space using delete

       delete [] pcBaseAddress;

   }


Shared memory

Table 2. Shared memory mapping

OS/2LinuxClassification
Named Shared Memory
DosAllocSharedMem
DosGetNamedSharedMem
shmget
shmat
Mappable
DosFreeMem shmdt
shmctl
Mappable

Shared memory is memory that two or more applications can read from and write to. Shared memory is prepared in such a way that any application can receive a pointer to the memory and access the data. Applications must explicitly request access to shared memory; the shared memory is protected from applications that are not granted access.

Types of shared memory

In OS/2 has two kinds of shared memory: named and unnamed.

With named shared memory, any application that knows the name of the shared memory can access it.

With unnamed shared memory, a pointer to the shared memory must be passed from the process that created the shared memory to the process being given access through some IPC mechanism.

In Linux, shared segments are always named (identified by a key). Unnamed shared segments are not supported.

Named shared memory

In OS/2, the call DosAllocSharedMem() allocates a shared memory object within the virtual address space. Allocating a shared memory object causes the creation of an object that describes a region of memory that can be shared. The virtual address space for a shared memory object is reserved at the same location in the virtual address space of every process. This allows any process to gain access to the shared object at the same virtual address where it was originally allocated:

APIRET DosAllocSharedMem(PPVOID ppb, PSZ pszName, ULONG cb, ULONG
flag);

  • ppb is a pointer to a variable that will receive the base address of the allocated range of pages
  • pszName is a shared memory name; for example, \SHAREMEM\PUBLIC.DAT
  • cb is size, in bytes, of the shared memory object to allocate
  • flag is the allocation attribute and desired access protection flags

Other processes can access the shared memory object through the shared memory name using DosGetNamedSharedMem(). To specify the name for the shared memory object, the name string provided must include the prefix "\SHAREMEM\". Getting a named shared memory object allocates the virtual address (of the shared memory object) in the virtual address space of the process:

APIRET DosGetNamedSharedMem(PPVOID ppb, PSZ pszName, ULONG flag);

  • ppb is the pointer to a variable that will receive the base address of the shared memory object
  • pszName is the address of the name string associated with the shared memory object
  • flag is the set of attribute flags that specify the desired access protection for the shared memory object

The system call DosFreeMem() is used to free the shared memory object.

In Linux, the system calls shmget() and shmat() must be used together to create or obtain access to the shared memory. shmget() returns the identifier of the shared memory segment associated to the value of the argument key. This key can be used to simulate the behaviour of the pszName parameter of DosAllocSharedMem. If shmflg is IPC_CREAT, it will create a new shared memory segment of a size equal to a multiple of PAGE_SIZE (it is rounded up to the next whole page). If this flag is not used, then shmget() will find the existing segment associated with key:

int shmget (key_t key , int size , int shmflg );

The system call shmat() attaches the shared memory segment identified by shmid to the address space of the calling process. shmid is returned by the call to shmget(), and the attaching address is specified by shmaddr. Setting it to zero will cause the operating system to choose the address. shmflg are the access protection flags. Set to SHM_RDONLY for read-only access, zero otherwise:

void *shmat ( int shmid, void *shmaddr, int shmflg);

To free shared memory, first make a call to shmdt() to detach the shared memory segment located at the address specified by shmaddr from the calling process's data segment:

int shmdt (void *shmaddr);

To completely free the shared memory, call shmctl() with the command IPC_RMID. This command can be executed only by a process that has an effective user ID equal to the value of shm_perm.cuid or shm_perm.uid in the data structure associated with shmid; or to a process that has superuser privileges. For freeing the memory, set buf to NULL:

int shmctl (int shmid, int cmd, struct shmid_ds *buf);

Examples


Listing 6. OS/2 shared memory


 /* This example allocates named shared memory as Read/Write, and commits it
during allocation. It also writes to it, and shows how other processes can
access it. */


   int main (VOID)

   {

      PVOID  pvShrObject = NULL;      	/* Pointer to shared memory
					   object      */

      PSZ    pszMemName  = "\\SHAREMEM\\MYTOOL\\APPLICAT.DAT";
					/* Object  name */

      PVOID  pvAltObject = NULL;      	/* Alternate pointer to shared
   					memory   */

      APIRET rc          = NO_ERROR;  	/* Return code */

      ULONG  ulObjSize   = 1024;   	/* Size (system rounds to 4096
					- page body */


      rc = DosAllocSharedMem(&pvShrObject,   /* Pointer to object
   						pointer  */

                             pszMemName,     /* Name for shared
   	 					memory   */

                             ulObjSize,      /* Desired size of
   						object   */

                             PAG_COMMIT |    /* Commit
   						memory   */

                             PAG_WRITE );    /* Allocate memory as
   						read/write */

      if (rc != NO_ERROR) {

         printf("DosAllocSharedMem error:  return code = %u\n",rc);

         return 1;

      }


      strcpy(pvShrObject, "Write your shared application data here.");


      rc = DosGetNamedSharedMem(&pvAltObject,  /* Pointer to pointer
   							of object */

                                pszMemName,    /* Name of shared
   						memory        */

                                PAG_READ);     /* Want read-only
   						access        */

      if (rc != NO_ERROR) {

         printf("DosGetNamedSharedMem error:  return code = %u\n",rc);

         return 1;

      }

      printf("Shared data read was \"%s\"\n",pvAltObject);

      rc = DosFreeMem(pvShrObject);

      if (rc != NO_ERROR) {

         printf("DosFreeMem error:  return code = %u\n",rc);

         return 1;   }


      return NO_ERROR;

   }


Listing 7. Linux shared memory

  	// In the following example, Process 1 allocates the shared memory
	// and writes its process id to the shared memory. Process 2 obtains
	// access to the memory and prints out process id of Process 1.
	// In production code, you would also need to include error-checking;
 	// this code sample assumes that all calls are successful.


   Process 1



   #include <sys/types.h>

   #include <sys/shm.h>


   #define  APP_SHARED_MEMORY  0x20

   typedef struct {

         int iPID;

   } shared_t;


   shared_t  *shared_mem;  // The address of the shared memory

   int iShmId;             // The shared mem identifier


   // The shared memory is allocated, It is indentified by the key
   // APP_SHARED_MEMORY. This same key must be used by process 2
   // to obtain access to the shared memory

   iShmId = shmget (APP_SHARED_MEMORY, sizeof(shared_t), IPC_CREAT);


   shared_mem = (shared_t *) shmat ( iShmid, 0, 0);	// Obtain the shared
   memory address

   shared_mem-> iPID = getpid();                   	// Write the process
   id to the shared mem


   // Wait for a signal or do some processing

   :

   :

   shmdt(shared_mem);  			// Detach the shared memory reference



   Process 2



   #include <sys/ipc.h>

   #include <sys/shm.h>

   #define APP_SHARED_MEMORY 0x20

   typedef struct {

         int iPID;

   } shared_t;


   shared_t  *shared_mem;  // The address of the shared memory

   int iShmId;             // The shared mem identifier


   // Obtain the id of shared memory indentified by key APP_SHARED_MEMORY

   iShmId = shmget (APP_SHARED_MEMORY, sizeof(shared_t), 0);


   shared_mem = (shared_t *) shmat ( iShmid, 0, 0);  // Obtain the shared
   						    //	memory address


   // print out the  process id of process 1

   printf ("Process 1 PID %d\n" , shared_mem-> iPID);



   // Detach and remove the shared memory

   shmdt(shared_mem);

   shmctl(iShmId, IPC_RMID, NULL);


   :

   :

Getting total physical memory

In OS/2, DosQuerySysInfo is used to get the total physical memory:

APIRET DosQuerySysInfo (istart, ilast, pBuf, cbBuf)

  • istart is the ordinal of the first system variable to return
  • ilast is the ordinal of the last system variable to return
  • pBuf is the address of the data buffer where the system returns the variable values
  • cBuf is the length in bytes of the data buffer

The system call DosQuerySysInfo returns the values of static variables. Common parameters include:

  • QSV_TOTPHYSMEM: the total number of bytes of physical memory in the system.
  • QSV_TOTRESMEM: the total number of bytes of resident memory in the system.
  • QSV_TOTAVAILMEM: the maximum number of bytes of memory that can be allocated by all processes in the system.

On Linux, the system call sysinfo is used to get the total physical memory:

int sysinfo (struct sysinfo *info )


Table 3. System information mapping table
OS/2 Linux Classification
DosQuerySysInfo sysinfo Mappable

Prior to Linux 2.3.16, sysinfo gave sizes in bytes and returned information in the following structure:


Listing 8. Total physical memory, prior to Linux 2.3.16
                 struct sysinfo {
                      long uptime;              /* Seconds
   						since boot */
                      unsigned long loads[3];   /* 1, 5, and 15 minute
   						load averages */
                      unsigned long totalram;   /* Total usable main
   						memory size */
                      unsigned long freeram;    /* Available memory
   						size */
                      unsigned long sharedram;  /* Amount of shared
						memory */
                      unsigned long bufferram;  /* Memory used by
						buffers */
                      unsigned long totalswap;  /* Total swap space
						size */
                      unsigned long freeswap;   /* swap space still
   						available */
                      unsigned short procs;     /* Number of current
   						processes */
                      char _f[22];              /* Pads structure
   						to 64 bytes */
                 };

From Linux 2.3.23 (on i386) and 2.3.48 (all architectures), sizes are given as multiples of mem_unit bytes, and the structure is:


Listing 9. Total physical memory, from Linux 2.3.23 (on i386) and 2.3.48 (all architectures)
                 struct sysinfo {
                      long uptime;    		/* Seconds
   						since boot */
                      unsigned long loads[3];   /* 1, 5, and 15 minute
   						load averages */
                      unsigned long totalram;   /* Total usable main
   						memory size */
                      unsigned long freeram;    /* Available memory
   						size */
                      unsigned long sharedram;  /* Amount of shared
						memory */
                      unsigned long bufferram;  /* Memory used by
						buffers */
                      unsigned long totalswap;  /* Total swap space
						size */
                      unsigned long freeswap;   /* swap space still
   						available */
                      unsigned short procs;     /* Number of current
   						processes */
                      unsigned long totalhigh;  /* Total high memory
   						size */
                      unsigned long freehigh;   /* Available high
   						memory size */
                      unsigned int mem_unit;    /* Memory unit size in
   						bytes */
                      char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding
   						              for libc5 */
                 };

Examples


Listing 10. Physical memory size in OS/2
   usigned long ulPhysMem;


   // Get the total number of bytes of physical memory in this system.


   DosQuerySysInfo(QSV_TOTPHYSMEM, QSV_TOTPHYSMEM, &ulPhysMem,
   sizeof(ulPhysMem));



   // ulPhysMem will have the total physical memory in bytes

   printf("The total physical memory in bytes is %ld\n", ulPhysMem);


Listing 11. Physical memory size in Linux

   struct sysinfo s_info;


   ....


   sysinfo(&s_info);


   // the sysinfo structure has the total physical memory of the system.

   printf(" The total physical memory available is %ld\n in Bytes",
   (s_info.totalram * mem_unit));


Pipes

Pipes are used for interprocess communications in both OS/2 and Linux. Processes can write to or read from the pipe as if it were standard output or standard input. Pipes are bi-directional. OS/2 returns a single handle when a pipe is created, and this handle is used for bi-directional communication between processes. Linux pipes are also bi-directional, but they return two handles: a read handle and a write handle.

Consider the following points when mapping pipes:

  • Size
    In OS/2, pipe size can be specified with a parameter. On Linux, the kernel sets the pipe size to be 4096 bytes, and this cannot be changed by a user application.
  • Type
    Are the pipes named or unnamed? Unnamed pipes behave the same way in OS/2 and on Linux. Named pipes on OS/2 allows processes from different machines to communicate with each other. Linux restricts such communication to a single machine. To achieve OS/2 behavior on Linux, you can use client-server programming techniques (TCP/IP Sockets).

Table 4. Pipes mapping table
OS/2 Linux Classification
DosCreatePipe
DosCreateNPipe (Server side)
DosConnectNPipe (Server Side)
DosOpen (Client side)
pipe
mkfifo
open
Context-specific
DosWrite
DosRead
write
read
Mappable
DosDisconnectNPipe (Server)
DosClose (Client)
close Context-specific

Unnamed pipes

In OS/2, the system call DosCreatePipe() is used to create a pipe:

APIRET DosCreatePipe (HFILE hReadPipe, HFILE hWritePipe, ULONG cb)

  • hReadPipe and hWritePipe are pointers to the read and write handle of the pipe
  • cb is used to set the size of the pipe

In Linux, the system call pipe is used to create an unnamed pipe:

int pipe (int filedes[])

  • filedes[0] and filedes[1] are pointers to the read and write handles of the pipe.

Named pipes

In OS/2, named pipes are used to communicate between related or unrelated processes running on the same machine -- or even on different machines. One process (the server process) creates a named pipe and connects to it. The client processes then connect to the other end of the pipe and then pass data back and forth by reading from and writing to the pipe.

The system call DosCreateNPipe() is used to create a named pipe in OS/2:

APIRET DosCreateNPipe (PSZ pszName, PHPIPE pHpipe, ULONG openmode,
ULONG pipemode, ULONG cbOutbuf, ULONG cbInbuf, ULONG msec)

  • pszName is the ASCII name of the pipe
  • pHpipe is the pipe handle
  • openmode is the set of flags defining the mode in which to open the pipe
  • pipemode is the set of flags defining the pipe mode
  • cbOutbuf and cbInbuf are the number of bytes to allocate for the outbound (server to client) and inbound (client to server) buffer
  • msec is the maximum time to wait in milliseconds for that named pipe instance to become available

The system call DosConnectNPipe() is used by the server process to connect to the pipe on one end. This puts the pipe to listen mode, and client processes can now access the pipe using DosOpen():

APIRET DosConnectNPipe (HPIPE hpipe)

  • hpipe is the pipe handle returned by DosCreateNPipe()

The system call DosOpen() allows the client process to gain access to the named pipe created by the server in listen mode:

APIRET DosOpen(PSZ pszFileName, PHFILE pHf, PULONG pulAction, ULONG
cbFile,ULONG ulAttribute, ULONG fsOpenFlags, ULONG fsOpenMode,
ULONG peaop2)

  • pszFileName is the ASCII value of the named pipe's name
  • pHf contains the handle to the named pipe.

In Linux, named pipes (FIFOs) are used to communicate between processes running on the same machine. mkfifo() is used to create a named pipe (FIFO) on Linux. After creating the FIFO, the open() system call is used to open the FIFO and further read/write operations can be performed:

int mkfifo(const char * pathname , mode_t mode )

  • pathname is the name of the named pipe
  • mode specifies the FIFO's permissions

In Linux, open() is used to open the FIFO, and the filename is the ASCII name of the file (FIFO):

int open (const char * filename, int flags )
int open (const char * filename, int flags, mode_t mode)

Reading and writing data using pipes

In OS/2, the DosRead() system call is used to read data from named and unnamed pipes alike. hFile is the handle to the read end of the pipe:

APIRET DosRead (HFILE hFile, PVOID pBuffer, ULONG cbRead, PULONG
pcbActual)

In Linux, the read() system call is used to read data from the pipe, while fd is the handle to the read end of the pipe:

size_t read(int fd, void *buf, size_t count)

In OS/2, the DosWrite() system call is used to write to the pipe. hFile is the handle to the write end of the pipe:

APIRET DosWrite(HFILE hFile, PVOID pBuffer, ULONG cbWrite, PULONG
pcbActual )

In Linux, the write() system call is used to write data to the pipe. fd is the handle to the write end of the pipe:

ssize_t write(int fd, const void *buf, size_t count)

Closing pipes

For named pipes in OS/2, the server process uses DosDisConnectNPipe() to disconnect a client process. Generally, client processes first issues DosClose() to close the pipe and then the server disconnects the pipe. But the server can disconnect before the client does, forcing the client to close the pipe. For unnamed pipes, DosClose() alone is sufficient to close the connection:

APIRET DosDisConnectNPipe (HPIPE hpipe)
APIRET DosClose (HPIPE hpipe)

  • hpipe is the handle to the read/write end of the pipe

On Linux, a close call is used to close the FIFO. fd is the handle to the read/write end of the FIFO:

int close (int fd)

Examples


Listing 12. Unnamed pipes in OS/2

   /*
   In this example, thread 1 creates an unnamed pipe, and writes to the
   pipe. Thread 2 reads the data once it becomes available.
   */

   HFILE    ReadHandle  = 0;          /* Read handle of pipe */

   HFILE    WriteHandle = 0;          /* Write handle of pipe */

   ULONG    PipeSize    = 4096;       /* Size of pipe */

   APIRET   rc          = NO_ERROR;   /* API return code */


Thread 1


   // Create pipe

   rc = DosCreatePipe(&ReadHandle, &WriteHandle, PipeSize);

   // get access to the pipe

   ...

   // Write to pipe

   rc = DosWrite(&WriteHandle,&cBuf, &len, &ulWrote);

   ...


   // Close write handle

   rc = DosClose(&WriteHandle);




Thread 2

   // wait for the data to come

   // Read from pipe

   rc = DosRead(&ReadHandle, &cBuf, &ulLen, &ulRead);

   ..

   // Close read handle

   rc = DosClose(&ReadHandle);


Listing 13. Named pipes in OS/2

   // Client program
   // This client program opens a named pipe, and connects to the
   // server. It writes messages to the pipe and closes the pipe
   // when it has no more data to write.
   # define PIPE_NAME \\PIPE\\EXAMPLE
   #define BUF_SIZE 255
   /* Pipe handle */
   HFILE PipeHandle = NULLHANDLE;

   ULONG    bytes    = 0;
   ULONG    Action   = 0;
   APIRET retCode = NO_ERROR; //Return code
   CHAR  message[BUF_SIZE +1]   = "";         /* Message buffer */
    // Open the pipe
   rc = DosOpen(PIPE_NAME,
                &PipeHandle,
                &Action,
                0, 0,
                FILE_OPEN,
                OPEN_ACCESS_READWRITE |
                OPEN_SHARE_DENYREADWRITE |
                OPEN_FLAGS_FAIL_ON_ERROR,     NULL);

   do {
      rc = DosWrite(PipeHandle, message,  strlen(message), &bytes);
          ....
          ....
          // end of message
          done = 1;
   } while (!done);
   // close the write handle of PIPE
   rc = DosClose(PipeHandle);

   // Server program
   // This Server program opens a named pipe, and waits for a client
   // connection. It writes messages to the pipe, and closes the pipe
   // when it finds no data to write
   # define PIPE_NAME \\PIPE\\EXAMPLE
   #define BUF_SIZE 255
   HPIPE PipeHandle = NULLHANDLE;//Pipe handle
   ULONG ulBytes = 0;//Bytes read /written
   CHAR message[BUF_SIZE + 1]  = "";            /* Input/Output
						    buffer */

   APIRET retCode = NO_ERROR;  			/* Return code */
   // create a named pipe
   retCode = DosCreateNPipe(PipeName,           /* Name of pipe to
   						    create */
                          &PipeHandle,      /* Handle returned
   						    for pipe */
                          NP_ACCESS_DUPLEX,     /* Duplex pipe */
                          NP_WAIT |
                          NP_TYPE_MESSAGE |
                          NP_READMODE_MESSAGE |
                          NP_WMESG |               /* Write messages */
                          NP_RMESG |               /* Read messages */
                          0x01,                    /* Unique instance of
   							pipe */
                          sizeof(message),         /* Output buffer size */
                          sizeof(message),         /* Input buffer size */
                          0L);                     /* Use default
   							time-out */
      // wait for connection
      retCode = DosConnectNPipe(PipeHandle);
      do {
          // connected, read the data
          retCode = DosRead(PipeHandle, message,
                   sizeof(message),&ulBytes);
          // display the message
          printf("\n\nMessage received was: %s\n\n", message);
          ..
          // end of message
          done = 1;
      } while (!done);
      // end of message, disconnect
      rc = DosDisConnectNPipe(PipeHandle);


Listing 14. Unnamed pipes in Linux

   /*
   In this example, thread 1 creates an unnamed pipe, and writes to the
   pipe. Thread 2 reads the data once it is available in the unnamed pipe.
   */


Thread 1

   int data_processed;

   int file_pipes[2];

   const char some_data[] = "123";


   // Create pipe

   pipe(file_pipes);


   // Get access to pipe


   // Write to pipe

   data_processed = write(file_pipes[1], some_data, strlen(some_data));


   // Close the write handle

   close(file_pipes[1]);


Thread 2

   int data_processed;

   char buffer[BUFSIZ + 1];


   // get access to pipe

   ..

   // read from pipe

   data_processed = read(file_pipes[0], buffer, BUFSIZ);


   // close the read handle

   close(file_pipes[0]);


Listing 15. Named pipes (FIFOs) in Linux


   // Client program
   /* This client program logs a message to the FIFO, and closes the
   write end when it finds no message to write */

   # define FIFO_NAME "/home/guest/testpipe"
   # define BUF_SIZE 2552
   int     retCode    = 0 ;
   FILE    *fd;
   int     done       = 0;
   char    buff[BUF_SIZE+1];
   int     dataWrite  = 0;
   // Open the FIFO with write permission
   fd = open (FIFO_NAME, O_WDONLY);
   do {
       // read from fifo
       // display the message

       strcpy(buffer, "test message");

       dataWrite = write(fd, buffer, BUF_SIZE);


       ....

       // done with all the messages
       done =1 ;
   } while(!done);
   // Close the write end of the FIFO
   fclose(fd);

   //Server program
   /* This Server program creates a FIFO, and waits for a message. If
   the message is available, it prints the message to screen.
   It closes the read end when it finds no message to read */

   # define FIFO_NAME "/home/guest/testpipe"
   # define BUF_SIZE 2552
   int     retCode  = 0 ;
   FILE    *fd;
   int     done     = 0;
   char    buff[BUF_SIZE+1];
   // create a FIFO with user having write and read permission, and
   // group and others having read permission.
   retCode = mkfifo(FIFO_NAME, S_IWUSR | S_IRUSR |
                   S_IRGRP | S_IROTH);
   // Open the FIFO with read permission
   fd = open (FIFO_NAME, O_RDONLY);
   do {
       // read from fifo
       // display the message

       dataRead = read(fd, buffer, BUF_SIZE);

       // display the message

       ....

       done =1 ;
   } while(!done);
   fclose(fd);


File-related calls

Query information about a file

OS/2 stores additional information about files in Extended attributes. Linux does not support this option.


Table 5. File info mapping table
OS/2 Linux Classification
DosQueryPathInfo stat Mappable

Getting file information

In OS/2, the system call DosQueryPathInfo is used to get information about a file or directory:

APIRET DosQueryPathInfo (pszPathName, ulInfoLevel, pInfoBuf,
cbInfoBuf)

  • pszPathName is a pointer to the name of the file or directory
  • ulInfoLevel is the level of the information required. 1, 2, 3, 5 are valid values. Level 4 is reserved.
  • pInfoBuf is the address of the storage area containing the requested level of path information:
    • Level 1: filestatus 3 is obtained, which contains basic file information: things like create date/time, last access date/time, and so on.
    • Level 2: filestatus 4 is obtained. This is the same as filestatus 3 with an additional field showing the size of the extended attributes. Level 2 is used to query the size of the extended attributes before reading.
    • Level 3: a subset of EA (extended attribute) information about a file is obtained. This information is used to:
      • Store notes on file objects (for example, the name of the file creator)
      • Categorize file objects (for example, source, samples, icons, bitmaps)
      • Describe the format of data contained in the file object (for example, a data record)
      • Append additional data to the file object
    • Level 4: is reserved
    • Level 5: gives the fully qualified file name.
  • cbInfoBuf is the length in bytes of the storage area pInfoBuf.

On Linux, the system call stat is used to get information about a file or directory

int stat (const char *pcPathName, struct stat *pBuf)

  • pcPathName is a pointer to the name of the file or directory
  • pBuf is a pointer to the structure containing the file/directory information. The structure holding the file or directory information is shown in Listing 16.

Listing 16. Structure containing the file/directory information
   struct stat {
       dev_t          st_dev;         	/* device */
       ino_t           st_ino;         	/* inode */
       mode_t       st_mode;     	/* protection */
       nlink_t       st_nlink;      	/* number of hard links */
       uid_t           st_uid;         	/* user ID of owner */
       gid_t           st_gid;         	/* group ID of owner */
       dev_t          st_rdev;       	/* device type (if inode device) */
       off_t            st_size;        /* total size, in bytes */
       blksize_t    st_blksize;  	/* blocksize for filesystem I/O */
       blkcnt_t     st_blocks;   	/* number of blocks allocated */
       time_t         st_atime;     	/* time of last access */
       time_t         st_mtime;    	/* time of last modification */
       time_t         st_ctime;		/* time of last change */
   };

Please note that DosQueryPathInfo fails if the file object is currently being updated by any other process that holds conflicting sharing and rights access. To prevent this, open the file object in a deny-write sharing mode.

The Linux stat call does not require any access rights to the file being accessed; it only requires search rights to all the directories in the path.

Examples


Listing 17. Query information about a file in OS/2


   char * pcPathAndCalFileName = "C:/test.Tbl";      // old file name

   char * pcPathAndOldFileName = "C:/test.Old";      // new file name

   FILESTATUS3 fsStatBuf;                            // structure filled
   by DosQueryPathInfo


   //
   // Rename the current test file, if it exists, to get ready for
   // calibration


   if (!DosQueryPathInfo(pcPathAndCalFileName, FIL_STANDARD, &fsStatBuf,
   sizeof(fsStatBuf))){

   if (!DosQueryPathInfo(pcPathAndOldFileName,
   FIL_STANDARD,

                                       &fsStatBuf, sizeof(fsStatBuf))){


   // Remove the old calibration data file "test.Old"

               remove(&pcPathAndOldFileName[0]);

         }


   // Rename the current "test.Tbl" test data file to the name
   //  "test.Old" that is used for old test data.


         rename( &pcPathAndCalFileName[0], &pcPathAndOldFileName[0] );

   }



Listing 18. Query information about a file on Linux

   char * pcPathAndCalFileName = "/home/guest/test.tbl";   // old file name

   char * pcPathAndOldFileName = "/home/guest/test.old";   // new file name


   struct stat buf;                                        // buffer with
							   // file information

   if (stat(pcPathAndCalFileName, &buf) == 0){


   // File exists so rename it. Before that check if `test.old' exists.
   // If yes then remove that file


   if (stat(pcPathAndOldFileName, &buf) == 0){


   remove(pcPathAndOldFileName);

   // Errors returned by this call should be handled appropriately

   }


   rename(pcPathAndCalFileName, pcPathAndOldFileName)


   // More error handling

   }

   else

   {

               //
               // File does not exist
               //

   }


Duplicating file handles

There are two ways to duplicate file descriptors: a new handle is allocated, or some known handle is used as a new handle.

On OS/2, DosDupHandle() supports both features. On Linux, if a new handle is to be allocated, the system call dup() is used, while in cases where a known handle is used as a new handle, the system call dup2() is used.


Table 6. Mapping table for duplicating file handles
OS/2 Linux Classification
DosDupHandle dup
dup2
Mappable

On OS/2, the system call DosDupHandle() is used to duplicate file handles:

APIRET DosDupHandle(HFILE hFile, PHFILE pHfile);

  • hFile takes the file handle to duplicate
  • phFile is a pointer to where the handle information is stored

Possible values are:

  • 0xFFFFFFFF
    a new file handle is allocated and returned.
  • Any other value
    Assign this value as the new file handle. A valid value is any of the handles assigned to standard I/O, or the handle of a file currently opened by the process.

Linux uses the dup() system call. When DosDupHandle() is used with a second paramater (like 0xFFFFFFFF) in OS/2, the 0xFFFFFFFF simply means to allocate a new handle. On Linux, dup provides the same functionality: the dup() system call returns the new file descriptor. dup2(), meanwhile, duplicates the file descriptor onto the passed in file descriptor:

int dup(int oldfd)
int dup2(int oldfd, int newfd)

  • oldfd is the file descriptor that has to be duplicated
  • newfd is the file descriptor that oldfd is duplicated onto

Examples

The following examples compare duplication of file handles under OS/2 and under Linux:


Listing 19. Duplicating file handles in OS/2

   enum    {

   StandardOutput = 0x00000001,       // for standard output

   StandardError  = 0x00000002,       // for standard error

   AllocNewHandle = 0xFFFFFFFF        // for allocating a new handle

   }


   HFILE hfOut, hfErr, hfSaveOut, ulSaveErr;

   unsigned long ulRet;


   //
   // Set the standard handles
   //


   hfOut = StandardOutput;

   hfSaveOut = (HFILE) AllocNewHandle;

   hfErr = StandardError;

   hfSaveErr = (HFILE) AllocNewHandle;


   //
   // Save the original handles.
   //

   DosDupHandle(hfOut, &hfSaveOut);

   DosDupHandle(hfErr, &hfSaveErr);


   //
   // Assign some other file handle or pipe handle to the to the standard
   // output & error
   //

   ulRet = DosDupHandle(hpWrite, &hfOut);

   ulRet = DosDupHandle(hpWrite, &hfErr);

   :  :  Do some processing

   : 

   //
   // Retrieve the original handles.
   //

   ulRet = DosDupHandle(hfSaveOut, &hfOut);

   ulRet = DosDupHandle(hfSaveErr, &hfErr);


   //
   // Close the temporary handles
   //

ulRet = DosClose(hfSaveErr);

   ulRet = DosClose(hfSaveOut);


Listing 20. Duplicating file handles in Linux

   enum    {

   StandardOutput = 1,        //for standard output

   StandardError  = 2,        //for standard error

   }


   // Instead of HFILE, in Linux the file descriptor is
   // an integer

   int fdOut, fdErr, fdSaveOut, fdSaveErr;

   int iRet;


   //
   // Set the standard handles
   //

   fdOut = StandardOutput;

   fdErr = StandardError;


   //
   // Save the original handles.
   //

   fdSaveOut = dup(fdOut);

   fdSaveErr = dup(fdErr);


   //
   // Assign some other file handle or pipe handle to the to the
   // standard output and error
   //

   fdOut = dup2 (hpWrite, fdOut);

   fdErr = dup2 (hpWrite, fdErr);

   :  : Do some processing

   : 

   //
   // Retrieve the original handles.
   //

   fdOut = dup2(fdSaveOut, fdOut);

   fdErr = dup2(fdSaveErr, fdErr);


   //
   // Close the temporary handles
   //

   close(fdSaveErr);

   close(fdSaveOut);

Changing the file access time


Table 7. File access mapping table
OS/2 Linux Classification
DosSetPathInfo utime Mappable

In OS/2 the system call DosSetPathInfo() is used:

APIRET DosSetPathInfo (PSZ pszPathName, ULONG ulInfoLevel,
PVOID pInfoBuf, ULONG cbInfoBuf, ULONG flOptions)

  • pszPathName is a pointer to the ASCII full path name of the file or sub directory.
  • ulInfoLevel is the level of file directory information being defined. Valid values are 1 and 2.
  • pInfoBuf is a pointer to the information being set.
    • Level 1
      For Level 1, FILESTATUS3 is passed. It contains the standard information of the file such as file creation date/time, acess date/time etc.
    • Level 2
      For Level 2, EAOP2 structure is passed. This sets the extended attribute value of the file. OS/2 stores the additional information about the file in the extended attrribute list (EA).

The DosSetPathInfo() not only sets the access/modification time of file or sub directory, it also sets the other parameters like file creation date/time, file size, and attributes of the file. However, in this section we only discuss changing the access/modification time. So we are using Level 1 and passing the FILESTATUS3 structure containing the new access/modified time.

On Linux, the system call utime() is used for changing the access time for a specified file:

int utime(const char * filename, struct utimbuf * buf );

  • filename is the pointer to the ASCII filename of the file whose access time needs to be modified.
  • buf is the pointer to the structure containing the new access/modified time for the file. utimbuf structure is given below.
   struct utimbuf {
           time_t actime;  	/* access time */
           time_t modtime; 	/* modification time */
   };

Examples


Listing 21. Setting file information in OS/2


   char *pcFileName= "xyz.ini";

   FILESTATUS3 fs3DirInfo;


   /* get the file information */

   DosQueryPathInfo(pcFileName, FIL_STANDARD, &fs3DirInfo,
   sizeof(fs3DirInfo));


   /* get the current time */

   tm *ptm = localtime(&lTime);


   /* update the file information structure with the new modification
   time */

   fs3DirInfo.fdateLastWrite.day     = ptm->tm_mday;

   fs3DirInfo.fdateLastWrite.month   = ptm->tm_mon + 1;

   fs3DirInfo.fdateLastWrite.year    = ptm->tm_year - 80;

   fs3DirInfo.ftimeLastWrite.twosecs = ptm->tm_sec / 2;

   fs3DirInfo.ftimeLastWrite.minutes = ptm->tm_min;

   fs3DirInfo.ftimeLastWrite.hours   = ptm->tm_hour;


   /* set the new file information */

   DosSetPathInfo(pcFileName, FIL_STANDARD, &fs3DirInfo,
   sizeof(fs3DirInfo), 0);


Listing 22. Setting file access time in Linux


   struct utimbuf buf;

   int iRc;

   time_t tTime;

   tm *tmr;


   /* Get the local time  */

   tTime = time(0);

   localtime_r(&tTime,&tmr);


   /* Update the structure with the new modification time */

   buf.actime = buf.modtime = mktime(tmr);


   /* set the new file information */

   iRc = utime("check.txt", &buf);


Conclusion

This article covered the mapping of OS/2 to Linux with respect to memory management, IPC mechanisms, and file handling. While not exhaustive in terms of coverage; you can use it as a reference for undertaking any migration activity involving OS/2 to Linux. Please refer to the man pages for more detailed explanations of the Linux calls mentioned in this article. The next article in this series covers the mapping of system calls related to device driver interface, timer calls, and related issues.


Resources

About the authors

Dinakar Guniguntala holds a B.Eng. degree in Computer Engineering from REC Surat. He has been employed with IBM Global Services, India, since February 1998, where he works on operating system internals. He has worked on the OS/2 kernel, graphics engine, and filesytems, as well as on embedded Linux, the Linux kernel, and Linux thread libraries. He can be reached at dgunigun-at-in.ibm.com.

Sathyan Doraiswamy holds a B.Eng. degree in Electronics and Communications from University Visvesvaraya College of Engineering, Bangalore. He joined IBM India in June 1997. He works for Engineering & Technology Services and specializes in firmware for embedded and real time systems. He has vast programming experience on Windows and Linux device drivers and on VxWorks. You can contact him at dsathyan-at-in.ibm.com.

Anand K. Santhanam has a B.Eng. in Computer Science from Madras University, India. He has been in IBM Global Services (Software Labs), India, since July 1999. He is a member of the Linux Group at IBM, where he has worked with ARM-Linux, character/X-based device drivers, power management in embedded systems, PCI device drivers, and multithreaded programming in Linux. Other areas of interest are OS internals and networking. You can contact him at asanthan-at-in.ibm.com.

Srinivasan S. Muthuswamy has a B.Eng. in Computer Engineering from the Government College of Technology, Coimbatore, India. He has been in IBM Global Services, India since August 2000. He has worked on multithreaded applications in Linux and on Web applications using WSBCC/Java technologies/Websphere/MQSeries. He has also worked on Crystal Reports and Lotus Domino. You can contact him at smuthusw-at-in.ibm.com.

Rinson Antony has a Bachelor of Engineering degree in Computer Engineering from Bombay University, India. He has been in IBM Global Services, India since July 2000. He has worked on multithreaded applications in Linux and Web applications using Java technologies, Websphere, and XML. Other areas of interest are PCI device drivers and networking. You can contact him at arinson-at-in.ibm.com.

Brahmaiah Vallabhaneni has a B.Eng. degree from BITS, Pilani, India. He has been in IBM Global Services, India, since August 2002. He has worked on GNU C Compiler porting, character device drivers, power management in embedded systems, PCI device drivers, and multithreaded programming in Linux. Other areas of interest are Linux internals and networking. You can contact him at bvallabh-at-in.ibm.com.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Linux
ArticleID=11394
ArticleTitle=Migrate your apps from OS/2 to Linux: Part 2. Memory management, IPC, and file handling
publish-date=05052004
author1-email=dgunigun-at-in.ibm.com
author1-email-cc=tomyoung@us.ibm.com
author2-email=dsathyan-at-in.ibm.com
author2-email-cc=tomyoung@us.ibm.com
author3-email=asanthan-at-in.ibm.com
author3-email-cc=
author4-email=smuthusw-at-in.ibm.com
author4-email-cc=
author5-email=arinson-at-in.ibm.com
author5-email-cc=
author6-email=bvallabh-at-in.ibm.com
author6-email-cc=

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers