/>
VMS C example code: eight-cubed.com
errchk.h: ifndef __jfd__errchk #define __jfd__errchk #include <stsdef.h> #include <lib$routines.h> #define errchk_ret(arg) if (!($VMS_STATUS_SUCCESS(arg))) \ return(arg); #define errchk_sig(arg) if (!($VMS_STATUS_SUCCESS(arg))) \ (void)lib$signal(arg); #define errchk_stop(arg) if (!($VMS_STATUS_SUCCESS(arg))) \ (void)lib$stop(arg); #endif /* __jfd__errchk */
#include <stdio.h> #include <stdlib.h> #include <ssdef.h> #include <stsdef.h> #include <descrip.h> #include <prcdef.h> #include <lib$routines.h> #include <starlet.h> #include "errchk.h" /******************************************************************************/ int main (void) { static unsigned long int r0_status; static const $DESCRIPTOR (process_name_d, "ec_sys_creprc"); static const $DESCRIPTOR (image_name_d, "SYS$SYSTEM:LOGINOUT.EXE"); static const $DESCRIPTOR (command_proc_d, "SYS$MANAGER:SYLOGIN.COM"); static unsigned long int pid; r0_status = sys$creprc (&pid, &image_name_d, 0, 0, 0, 0, 0, &process_name_d, &command_proc_d, 0, 0, PRC$M_INTER|PRC$M_NOPASSWORD, 0, 0); errchk_sig (r0_status); (void)printf ("PID = %08x\n", pid); }
VMS: $creprc Creates, on behalf of the calling process, a subprocess or detached process on the current node, or a detached process on another OpenVMS Cluster node. Format SYS$CREPRC [pidadr] ,[image] ,[input] ,[output] ,[error] ,[prvadr] ,[quota] ,[prcnam] ,[baspri] ,[uic] ,[mbxunt] ,[stsflg] ,[itmlst] ,[node] ,[home_rad] C Prototype int sys$creprc (unsigned int *pidadr, void *image, void *input, void *output, void *error, struct _generic_64 *prvadr, unsigned int *quota, void *prcnam, unsigned int baspri, unsigned int uic, unsigned short int mbxunt, unsigned int stsflg,...); Arguments pidadr OpenVMS usage:process_id type: longword (unsigned) access: write only mechanism: by reference Process identification (PID) of the newly created process. The pidadr argument is the address of a longword into which $CREPRC writes the PID. image OpenVMS usage:logical_name type: character-coded text string access: read only mechanism: by descriptor-fixed-length string descriptor Name of the image to be activated in the newly created process. The image argument is the address of a character string descriptor pointing to the file specification of the image. The image name can have a maximum of 63 characters. If the image name contains a logical name, the logical name is translated in the created process and must therefore be in a logical name table that it can access. To create a process that will run under the control of a command language interpreter (CLI), specify SYS$SYSTEM:LOGINOUT.EXE as the image name. input OpenVMS usage:logical_name type: character-coded text string access: read only mechanism: by descriptor-fixed-length string descriptor Equivalence name to be associated with the logical name SYS$INPUT in the logical name table of the created process. The input argument is the address of a character string descriptor pointing to the equivalence name string. output OpenVMS usage:logical_name type: character-coded text string access: read only mechanism: by descriptor-fixed-length string descriptor Equivalence name to be associated with the logical name SYS$OUTPUT in the logical name table of the created process. The output argument is the address of a character string descriptor pointing to the equivalence name string. error OpenVMS usage:logical_name type: character-coded text string access: read only mechanism: by descriptor-fixed-length string descriptor Equivalence name to be associated with the logical name SYS$ERROR in the logical name table of the created process. The error argument is the address of a character string descriptor pointing to the equivalence name string. Note that the error argument is ignored if the image argument specifies SYS$SYSTEM:LOGINOUT.EXE; in this case, SYS$ERROR has the same equivalence name as SYS$OUTPUT. prvadr OpenVMS usage:mask_privileges type: quadword (unsigned) access: read only mechanism: by reference Privileges to be given to the created process. The prvadr argument is the address of a quadword bit mask wherein each bit corresponds to a privilege; setting a bit gives the privilege. If the prvadr argument is not specified, the current privileges are used. Each bit has a symbolic name; the $PRVDEF macro defines these names. You form the bit mask by specifying the symbolic name of each desired privilege in a logical OR operation. Refer to the HP OpenVMS System Services Reference Manual to view the table containing the symbolic name and description of each privilege. You need the user privilege SETPRV to grant a process any privileges other than your own. If the caller does not have this privilege, the mask is minimized with the current privileges of the creating process; any privileges the creating process does not have are not granted, but no error status code is returned. quota OpenVMS usage:item_quota_list type: longword (unsigned) access: read only mechanism: by reference Process quotas to be established for the created process. These quotas limit the created process's use of system resources. The quota argument is the address of a list of quota descriptors, where each quota descriptor consists of a 1-byte quota name followed by a longword that specifies the desired value for that quota. The list of quota descriptors is terminated by the symbolic name PQL$_LISTEND. If you do not specify the quota argument or specify it as 0, the operating system supplies a default value for each quota. Refer to the HP OpenVMS System Services Reference Manual to view MACRO and C examples, individual quota descriptions, and instructions for use of the quota list. prcnam OpenVMS usage:process_name type: character-coded text string access: read only mechanism: by descriptor-fixed-length string descriptor Process name to be assigned to the created process. The prcnam argument is the address of a character string descriptor pointing to a process name string. If a subprocess is being created, the process name is implicitly qualified by the UIC group number of the creating process. If a detached process is being created, the process name is qualified by the group number specified in the uic argument. baspri OpenVMS usage:longword_unsigned type: longword (unsigned) access: read only mechanism: by value Base priority to be assigned to the created process. The baspri argument is a longword value. The OpenVMS VAX range is 0 to 31, where 31 is the highest priority and 0 is the lowest. Usual priorities are in the range 0 to 15, and real-time priorities are in the range 16 to 31. The OpenVMS Alpha and I64 range is 0 to 63, with real-time priorities in the range 32 to 63. If you want a created process to have a higher priority than its creating process, you must have ALTPRI privilege to raise the priority level. If the caller does not have this privilege, the specified base priority is compared with the caller's priority and the lower of the two values is used. A process with ALTPRI privilege running on a VAX node can create a process with a priority greater than 31 on an Alpha or I64 node. If the baspri argument is not specified, the priority defaults to 2 for VAX MACRO, VAX BLISS-32, and Pascal; it defaults to 0 for all other languages. uic OpenVMS usage:uic type: longword (unsigned) access: read only mechanism: by value User identification code (UIC) to be assigned to the created process. The uic argument is a longword value containing the UIC. If you do not specify the uic argument or specify it as 0 (the default), $CREPRC creates a process and assigns it the UIC of the creating process. If you specify a nonzero value for the uic argument, $CREPRC creates a detached process. This value is interpreted as a 32-bit octal number, with two 16-bit fields: bits 0-15-member number bits 16-31-group number You need IMPERSONATE or CMKRNL privilege to create a detached process with a UIC that is different from the UIC of the creating process. If the image argument specifies the SYS$SYSTEM:LOGINOUT.EXE, the UIC of the created process will be the UIC of the caller of $CREPRC, and the UIC parameter is ignored. mbxunt OpenVMS usage:word_unsigned type: word (unsigned) access: read only mechanism: by value Unit number of a mailbox to receive a termination message when the created process is deleted. The mbxunt argument is a word containing this number. If you do not specify the mbxunt argument or specify it as 0 (the default), the operating system sends no termination message when it deletes the process. The Get Device/Volume Information ($GETDVI) service can be used to obtain the unit number of the mailbox. If you specify the mbxunt argument, the mailbox is used when the created process actually terminates. At that time, the $ASSIGN service is issued for the mailbox in the context of the terminating process and an accounting message is sent to the mailbox. If the mailbox no longer exists, cannot be assigned, or is full, the error is treated as if no mailbox had been specified. If you specify this argument when you create a process on another node, an accounting message will be written to the mailbox when the process terminates. If the node is removed from the cluster before the created process terminates, an accounting message will be simulated. The simulated message will contain the created process's PID and name and a final status of SS$_NODELEAVE, but will lack execution statistics. Note that two processes on different nodes cannot use the termination mailbox for general interprocess communication. The accounting message is sent before process rundown is initiated but after the process name has been set to null. Thus, a significant interval of time can occur between the sending of the accounting message and the final deletion of the process. To receive the accounting message, the caller must issue a read to the mailbox. When the I/O completes, the second longword of the I/O status block, if one is specified, contains the process identification of the deleted process. The $ACCDEF macro defines symbolic names for offsets of fields within the accounting message. Refer to the HP OpenVMS System Services Reference Manual to view the table describing the offsets, their symbolic names, and the contents of each field. stsflg OpenVMS usage:mask_longword type: longword (unsigned) access: read only mechanism: by value Options selected for the created process. The stsflg argument is a longword bit vector wherein a bit corresponds to an option. Only bits 0 to 22 are used; the others are reserved and must be 0. Each option (bit) has a symbolic name, which the $PRCDEF macro defines. You construct the stsflg argument by performing a logical OR operation using the symbolic names of each desired option. Refer to the HP OpenVMS System Services Reference Manual to view the table describing the symbolic name of each option. itmlst OpenVMS usage:reserved type: longword (unsigned) access: mechanism: 0 The itmlst argument is reserved by HP. node OpenVMS usage:SCS_nodename type: character-coded text string access: read only mechanism: by descriptor-fixed-length string descriptor Name of the OpenVMS Cluster node on which the process is to be created. The node argument is the address of a character string descriptor pointing to a 1- to 6-character SCS node name string. If the argument is present but zero or if the string is zero length, the process is created on the current node. home_rad OpenVMS usage:longword_unsigned type: longword (unsigned) access: read only mechanism: by value Sets the home resource affinity domain (RAD) of a process. The home RAD is determined by the operating system, unless you explicitly request one. If bit PRC$M_HOME_RAD in the stsflg is set, home_rad is the RAD on which the process is to start. Note that you may set this bit to 0 on non-RAD systems. Note: OpenVMS support for RADs is available only on the AlphaServer GS series systems. For more information about using RADs, refer to the HP OpenVMS Alpha Partitioning and Galaxy Guide.
Condition Values Returned SS$_NORMAL The service completed successfully. SS$_ACCVIO The logical name string or string descriptor cannot be read by the caller, or the channel number cannot be written by the caller SS$_BADPARAM The bufquo argument specified a value greater than approximately 65324, which is 65535 minus the size of a mailbox unit control block (UCB). SS$_EXBYTLM The process has insufficient buffer I/O byte count (BYTLM) quota to allocate the mailbox UCB or to satisfy buffer requirements. SS$_INSFMEM The system dynamic memory is insufficient for completing the service. SS$_INTERLOCK The bit map lock for allocating mailboxes from the specified shared memory is locked by another process. SS$_IVLOGNAM The logical name string has a length of 0 or has more than 255 characters. SS$_IVSTSFLG The bit set in the prmflg argument is undefined; this argument can have a value of 1 or 0. SS$_NOIOCHAN No I/O channel is available for assignment. SS$_NOPRIV The process does not have the privilege to create a temporary mailbox, a permanent mailbox, a mailbox in memory that is shared by multiple processors, or a logical name. SS$_NOSHMBLOCK No shared memory mailbox UCB is available for use to create a new mailbox. SS$_OPINCOMPL A duplicate unit number was encountered while linking a shared memory mailbox UCB. If this condition value is returned, contact your Digital support representative. SS$_SHMNOTCNCT The shared memory named in the name argument is not known to the system. This error can be caused by a spelling error in the string, an improperly assigned logical name, or the failure to identify the multiport memory as shared at system generation time. SS$_TOOMANYLNAM The logical name translation of the string named in the lognam argument exceeded the allowed depth.
** NOTE: this code compiles and runs and works (creates 3 notepad instances) when i use vc++ 6.0 could NOT make work in vc++ 2005.
/* simple example of using createProcess creates 3 instances of notepad CreateProcess Function Creates a new process and its primary thread. The new process runs in the security context of the calling process. If the calling process is impersonating another user, the new process uses the token for the calling process, not the impersonation token. BOOL WINAPI CreateProcess( __in LPCTSTR lpApplicationName, __in_out LPTSTR lpCommandLine, __in LPSECURITY_ATTRIBUTES lpProcessAttributes, __in LPSECURITY_ATTRIBUTES lpThreadAttributes, __in BOOL bInheritHandles, __in DWORD dwCreationFlags, __in LPVOID lpEnvironment, __in LPCTSTR lpCurrentDirectory, __in LPSTARTUPINFO lpStartupInfo, __out LPPROCESS_INFORMATION lpProcessInformation ); ** can do LOTS here... typedef struct { DWORD cb; LPTSTR lpReserved; LPTSTR lpDesktop; LPTSTR lpTitle; DWORD dwX; DWORD dwY; DWORD dwXSize; DWORD dwYSize; DWORD dwXCountChars; DWORD dwYCountChar; DWORD dwFillAttribute; DWORD dwFlags; WORD wShowWindow; WORD cbReserved2; LPBYTE lpReserved2; HANDLE hStdInput; HANDLE hStdOutput; HANDLE hStdError; } STARTUPINFO; undocumented features */ #include <iostream> #include <windows.h> #include <stdio.h> using namespace std; int main() { // windows structures STARTUPINFO si; PROCESS_INFORMATION pi; DWORD dwCode = 0; int x = 5; // function fills startup block of memory with zeros. ZeroMemory(&si, sizeof(STARTUPINFO)); // setup the startup DS for the create call after zeroing si.cb = sizeof (STARTUPINFO); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_SHOWNORMAL; // call in a loop for (int i = 0; i < 2; i++) { if (CreateProcess(NULL, "notepad.exe", NULL, NULL, 0, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi)) /* OR... STARTUPINFO si = { sizeof(si) }; PROCESS_INFORMATION pi; char szExe[] = "cmd.exe"; if(CreateProcess(0, szExe, 0, 0, FALSE, 0, 0, 0, &si, &pi)) { // optionally wait for process to finish WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } */ { //::Sleep(1000); cout << "The ID of notepad is " << pi.dwProcessId << endl; //while (WaitForSingleObject(pi.hProcess, 5000) == WAIT_TIMEOUT) { // cout << x << " "; // x += 5; //} cout << endl; // closing a handle does not terminate the associated thread. // to remove a thread object, you must terminate the thread, // then close all handles to the thread. // this just "cuts the cord" between mother & child CloseHandle(pi.hThread); CloseHandle(pi.hProcess); } //endif else cout << "Error creating process:" << GetLastError() << endl; } //endfor return 0; } // end main
When you execute a command in UNIX you are initiating a
process that is tracked by the OS.
A feature of UNIX is that processes can be generated by other processes.
This happens a lot. When you log in to your system you are running a
process, very probably the shell. If you run a job in the
background (&) then look at the processes (ps -f):
jupiter|/export/home/wyatt/private/NumberArrayNoReps$ ps -f
UID PID PPID C STIME TTY TIME CMD
wyatt 5996 5994 0 Oct 13 pts/13 0:00 -bash
wyatt 3923 5996 44 16:21:55 pts/13 0:43 timeRandomArray25
note that ppid of timeRandomArray25 is bash's PID (5996)
UNIX provides simple but powerful facilities for creating processes
and executing program images.
Two main system calls:
1. fork
creates a child process
memory, set of open files, and other system-maintained
components are ALL copied from the calling process
childpid = fork();
2. exec
overlays the address space of the calling process
with a new program image
execl("/bin/ls", "ls", "-l", NULL);
wait
waits (blocks) for next termination of a child of the calling process