Wiley.Developing.Software.for.Symbian.OS.2nd.Edition.Dec.2007 (779887), страница 55
Текст из файла (страница 55)
As I mentioned before, closing the handledoes not terminate the actual process it represents. We’ll discuss how todo that shortly, in section 9.1.8.RProcess::Open() returns KErrNone if successful, otherwise itreturns a system error. For example, if it cannot find the process IDsupplied in the Open() argument, then it returns KErrNotFound.9.1.5Process NamesEach process has an ASCII name associated with it. The default name fora process is the name of the EXE file that contains it, minus the directorypath and the .exe extension.282PROCESSES, THREADS, AND SYNCHRONIZATIONYou can open a handle to a process by its name using Open(TDesC&aName) in RProcess. Note, however, that the system automaticallyappends a UID and instance number to the name of the process, and youmust supply this full name to Open(TDesC& aName) for it to succeed.This can make opening a process by name using Open(TDesC& aName)awkward.A better way to open a process by name is to use the Open(TFindProcess& aFind) version of Open().
This call allows you to use awildcard match of the process name, as in the following example:RProcess proc;_LIT(KMatchName,"MyProc*");TFindProcess procName(KMatchName);TInt rc = proc.Open(procName);if (rc != KErrNone){/* open failed, handle error */}This code will open the first process it finds that starts with ‘MyProc’,which our myproc.exe example would match.
The actual process namewill look something like:"MyProc[00000000]0001"which is the name followed by a program UID (set by the RProcess::SetType() method) and an instance number – the kernel appends thelatter two items to the base process name automatically.TFindProcess is a class inherited from TFindHandleBase, whichis a generic class for searching through kernel objects of a specific typeand returning matches based on supplied match strings. TFindProcessspecifically looks for running processes whose names match the suppliedstring.9.1.6 Querying the Phone’s Running ProcessesYou can also use TFindProcess directly to traverse the list of processesin the system.
It has a method called Next() that you can use to stepthrough the filtered list (filtered by the match pattern) one at a time, andget each process’s full name.The next example shows how you can use TFindProcess to querya list of running processes on the phone.The default match string of TFindProcess is ‘*’, so this example simplytraverses the list of all processes in the system.PROCESSES283TFindProcess fp;TFullName procName;while(fp.Next(procName)==KErrNone){_LIT(KProcessName, "process: %S\n");console->Printf(KProcessName,&procName);}Let’s extend the example a bit and print some information about eachprocess using the RProcess GetMemoryInfo() method:void ListProcessesL(){TFindProcess fp;TFullName procName;TProcessMemoryInfo memInfo;RProcess process;while(fp.Next(procName)==KErrNone){User::LeaveIfError(process.Open(procName));process.GetMemoryInfo(memInfo);_LIT(KProcessFormatName,"Process: %S\n");console->Printf(KProcessFormatName,&procName);_LIT(KCodeBaseFormat, " code base=%x\n");console->Printf(KCodeBaseFormat,memInfo.iCodeBase);_LIT(KCodeSizeFormat, " code size =%x\n");console->Printf(KCodeSizeFormat,memInfo.iCodeSize);_LIT(KInitDataSizeFormat, " initialized data size=%x\n");console->Printf(KInitDataSizeFormat,memInfo.iInitialisedDataSize);LIT(KUninitSizeFormat, " uninitialized data size=%x\n");console->Printf(KUninitSizeFormat,memInfo.iUninitialisedDataSize);process.Close();}}A sample portion of output from this example showing the first fewprocesses follows:Process: ekern.exe[100041af]0001.code base=f8013000.code size =3b844.initialized data size=1bc.uninitialized data size=14dc.Process: efile.exe[100039e3]0001.code base=f813e698.code size =1aca4.initialized data size=d0.uninitialized data size=22c0.Process: domainSrv.exe[1020e406]0001.code base=f8172238.code size =1fdc.initialized data size=0.uninitialized data size=0.284PROCESSES, THREADS, AND SYNCHRONIZATION9.1.7 Process PriorityEach process is assigned a priority value.
The kernel uses process prioritiesto decide which process to switch to when more than one process isready for execution at a time.Use SetPriority() in RProcess to set the priority for a process.The priority can be one of the following (from the TProcessPriorityenum):•EPriorityLow (150)•EPriorityBackground (250)•EPriorityForeground (350)•EPriorityHigh (450).As an example, the following line changes the priority of the currentprocess to the highest priority:RProcess currproc;currproc.SetPriority(EPriorityHigh);By default, the RProcess class constructor opens a handle to thecurrently running process.
I could have skipped declaring currprocaltogether and replaced the last two lines with the line:RProcess().SetPriority(EPriorityHigh);This calls both the constructor and the method (this is a commonpractice).You can also set the process priority at build time, and not useRProcess at all. To do this, add the epocprocesspriority keyword to your EXE’s MMP file. Set the keyword to low, background,foreground or high (e.g., epocprocesspriority foreground).To read the priority of a process, use the RProcess::Priority()method – this will return the current priority of a process.9.1.8 Terminating a ProcessTypically, a process ends after running its course (i.e., returning fromits E32Main() function).
However, you can terminate a process beforethen by calling RProcess::Kill(). The method takes one integerargument – a code to indicate the reason the process was terminatedthrough a return value. A process can kill itself, or any other process ithas a handle to.PROCESSES285Your program will need the PowerMgmt extended capability and beSymbian Signed in order to perform a Kill() on a process if it is not theprocess in which the current thread is running. Otherwise the functionwill return KErrPermissionDenied (-46).
Please see Chapter 7 formore details about platform security.RProcess::Panic(const TDesC& aCategory,TInt aReason)also terminates a process. Panic() indicates that some unrecoverableerror was detected. aCategory is a string indicating the type of panic;aReason gives the specific error number.9.1.9 Checking the Status of a ProcessTo check if a process is still running and, if not, how and why itwas terminated, use the RProcess ExitType() and ExitReason()methods.ExitType() returns EExitKill if the process has ended – eithernormally, via a return from E32Main(), or forcibly, via an RProcess::Kill() call. ExitType() returns EExitPanic to indicate that theprocess has been terminated by a call to the RProcess::Panic()method.
If ExitType() returns EExitPending, this means that theprocess is still running.If ExitType() indicates that the process is no longer running (byreturning EExitKill or EExitPanic), then you can call ExitReason() to get more information about the termination reason. ExitReason() returns the value returned by the E32Main() function of theprocess for a normal exit, the reason code passed to the Kill() method,if Kill() was called, or, if the process has ended due to a Panic(),then ExitReason() will return the panic code.Why is a normal process exit reported in the same way as a forcedprocess Kill()? The reason is that whenever a process returns fromE32Main(), the system automatically calls Kill() on that process,passing E32Main()’s return value as the parameter to the Kill()function.9.1.10 Signaling when a Process EndsThe RProcess::Logon() method can be used to wait for a process tocomplete as follows:void StartProcessWaitEndL(){RProcess proc;User::LeaveIfError(proc.Create(MyExeFile));TRequestStatus stat;proc.Logon(stat);proc.Resume();// Thread is executing.
Can add code here to run in parallel...286PROCESSES, THREADS, AND SYNCHRONIZATIONUser::WaitForRequest(stat); // blocks here while process is running// Process is ended, you can use proc.ExitType()// proc.ExitReason() and proc.ExitCategory()// to get information on how the process ended.}RProcess::Logon() is an asynchronous function as indicated byits TRequestStatus argument.
Asynchronous functions are covered indetail in Chapter 8, along with active objects, but for simplicity here it issufficient to say that they always return immediately, and send an eventat a later time, when the function actually completes. On completion, theTRequestStatus variable contains the status of the completion.To realize the full power of asynchronous functions, you should usean active object to set up a callback to be run when the functioncompletes. But you can also simply wait for completion of the functionvia User::WaitForRequest(), as we did in the previous example,because my purpose here was just to introduce the Logon() method.Although the example code actually created the process in whichLogon() was called, you can also use Logon() on processes whichare already running, opened via RProcess::Open().