Tuesday 30 October 2007

quick luaunch

Quicksilver for Mac OSX

Katapult for Linux KDE (alt+space)

Gnome-launch-box for Linux Gnome

  1. Start gconf-editor from a terminal
  2. Locate /apps/metacity/keybindings_commands in the treeview
  3. Set a command, for example command_1 to gnome-launch-box
  4. Go to /apps/metacity/global_keybindings
  5. Setup the keybinding you want for running GNOME Launch Box as run_command_1

Friday 26 October 2007

nice (Unix)

From Wikipedia, the free encyclopedia

Jump to: navigation, search

nice (IPA pronunciation: /naɪs/) is a command found on UNIX and other POSIX-like operating systems such as Linux. nice directly maps to a kernel call of the same name. For a given process, it changes the priority in the kernel's scheduler. A nice value of −20 is the highest priority and 19 is the lowest priority. The default nice value for processes is inherited by its parent process, usually 0.

Nice becomes useful when several processes are demanding more resources than the CPU can provide. In this state, a higher priority process will get a larger chunk of the CPU time than a lower priority process. If the CPU can deliver more resources than the processes are requesting, then even the lowest priority process can get up to 99% of the CPU. Only the superuser (root) may set the nice value to a smaller (higher priority) value.

There is also a renice command, which is used to change the priority of a process that's already running.

The exact mathematical effect of setting a particular niceness value for a process depends on the details of how the scheduler is designed on that implementation of UNIX. A particular operating system's scheduler will also have various heuristics built into it, e.g., to favor processes that are mostly I/O-bound over processes that are CPU-bound. As a simple example, when two otherwise identical CPU-bound processes are running simultaneously on a single-CPU Linux system, each one's share of the CPU time will be proportional to 20-p, where p is the process's priority. Thus a process run with nice +15 will receive 1/4 of the CPU time allocated to a normal-priority process: (20-15)/(20-0)=1/4. On the BSD 4.x scheduler, on the other hand, the ratio in the same example is more like ten to one.

Contents

[hide]

[edit] Language bindings

[edit] C

nice
getpriority(2)

[edit] Perl

 use POSIX ();
POSIX::nice(7); # like the renice shell command; increase niceness level by 7
my $prio = getpriority(0,0); # like the C function

[edit] See also

[edit] External links

Linux Memory Usage

A lot of people made good points in the comments section of my last posting (Understanding memory usage on Linux). Here are some of the general ideas that were mentioned:

(1) Several comments noted that non-x86 hardware has a different approach to shared memory between processes. This is true; some architectures do not handle shared memory in the same way as x86. To be honest, I don't know which platforms those are, so I'm not going to even try to list them. Thus, my previous post should be taken with a big grain of salt if you're working on a non-x86 platform.

(2) Many people also noted that this shared library feature of Linux isn't some fancy new thing, which is completely true. Microsoft Windows platforms undoubtedly have the same basic sharing feature, just like any full-featured modern operating system. My post only addressed Linux because, to be honest, I'm a Linux-centric kind of person.

(3) Yes, I did commit the sin of using "it's" instead of "its". To all of the English majors in the audience, I offer my most sincere apology.

(4) A few comments mentioned the memory size of Firefox. I must admit that I began this article with Firefox instead of KEdit as the primary example, but I was forced to switch to KEdit when I saw how big Firefox's private/writeable size was; KEdit illustrated my point much better. :)

(5) If the word "marginal" that I used confused anyone, then feel free to just mentally replace it with the word "incremental".

Thanks to everyone that commented on the posting; part of my reason for writing it was to see what other people thought, as other people usually know more than I do about any given subject.

Saturday, February 04, 2006

Understanding memory usage on Linux

This entry is for those people who have ever wondered, "Why the hell is a simple KDE text editor taking up 25 megabytes of memory?" Many people are led to believe that many Linux applications, especially KDE or Gnome programs, are "bloated" based solely upon what tools like ps report. While this may or may not be true, depending on the program, it is not generally true -- many programs are much more memory efficient than they seem.

What ps reports
The ps tool can output various pieces of information about a process, such as its process id, current running state, and resource utilization. Two of the possible outputs are VSZ and RSS, which stand for "virtual set size" and "resident set size", which are commonly used by geeks around the world to see how much memory processes are taking up.

For example, here is the output of ps aux for KEdit on my computer:

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
dbunker 3468 0.0 2.7 25400 14452 ? S 20:19 0:00 kdeinit: kedit

According to ps, KEdit has a virtual size of about 25 megabytes and a resident size of about 14 megabytes (both numbers above are reported in kilobytes). It seems that most people like to randomly choose to accept one number or the other as representing the real memory usage of a process. I'm not going to explain the difference between VSZ and RSS right now but, needless to say, this is the wrong approach; neither number is an accurate picture of what the memory cost of running KEdit is.

Why ps is "wrong"
Depending on how you look at it, ps is not reporting the real memory usage of processes. What it is really doing is showing how much real memory each process would take up if it were the only process running. Of course, a typical Linux machine has several dozen processes running at any given time, which means that the VSZ and RSS numbers reported by ps are almost definitely "wrong". In order to understand why, it is necessary to learn how Linux handles shared libraries in programs.

Most major programs on Linux use shared libraries to facilitate certain functionality. For example, a KDE text editing program will use several KDE shared libraries (to allow for interaction with other KDE components), several X libraries (to allow it to display images and copy and pasting), and several general system libraries (to allow it to perform basic operations). Many of these shared libraries, especially commonly used ones like libc, are used by many of the programs running on a Linux system. Due to this sharing, Linux is able to use a great trick: it will load a single copy of the shared libraries into memory and use that one copy for every program that references it.

For better or worse, many tools don't care very much about this very common trick; they simply report how much memory a process uses, regardless of whether that memory is shared with other processes as well. Two programs could therefore use a large shared library and yet have its size count towards both of their memory usage totals; the library is being double-counted, which can be very misleading if you don't know what is going on.

Unfortunately, a perfect representation of process memory usage isn't easy to obtain. Not only do you need to understand how the system really works, but you need to decide how you want to deal with some hard questions. Should a shared library that is only needed for one process be counted in that process's memory usage? If a shared library is used my multiple processes, should its memory usage be evenly distributed among the different processes, or just ignored? There isn't a hard and fast rule here; you might have different answers depending on the situation you're facing. It's easy to see why ps doesn't try harder to report "correct" memory usage totals, given the ambiguity.

Seeing a process's memory map
Enough talk; let's see what the situation is with that "huge" KEdit process. To see what KEdit's memory looks like, we'll use the pmap program (with the -d flag):

Address Kbytes Mode Offset Device Mapping
08048000 40 r-x-- 0000000000000000 0fe:00000 kdeinit
08052000 4 rw--- 0000000000009000 0fe:00000 kdeinit
08053000 1164 rw--- 0000000008053000 000:00000 [ anon ]
40000000 84 r-x-- 0000000000000000 0fe:00000 ld-2.3.5.so
40015000 8 rw--- 0000000000014000 0fe:00000 ld-2.3.5.so
40017000 4 rw--- 0000000040017000 000:00000 [ anon ]
40018000 4 r-x-- 0000000000000000 0fe:00000 kedit.so
40019000 4 rw--- 0000000000000000 0fe:00000 kedit.so
40027000 252 r-x-- 0000000000000000 0fe:00000 libkparts.so.2.1.0
40066000 20 rw--- 000000000003e000 0fe:00000 libkparts.so.2.1.0
4006b000 3108 r-x-- 0000000000000000 0fe:00000 libkio.so.4.2.0
40374000 116 rw--- 0000000000309000 0fe:00000 libkio.so.4.2.0
40391000 8 rw--- 0000000040391000 000:00000 [ anon ]
40393000 2644 r-x-- 0000000000000000 0fe:00000 libkdeui.so.4.2.0
40628000 164 rw--- 0000000000295000 0fe:00000 libkdeui.so.4.2.0
40651000 4 rw--- 0000000040651000 000:00000 [ anon ]
40652000 100 r-x-- 0000000000000000 0fe:00000 libkdesu.so.4.2.0
4066b000 4 rw--- 0000000000019000 0fe:00000 libkdesu.so.4.2.0
4066c000 68 r-x-- 0000000000000000 0fe:00000 libkwalletclient.so.1.0.0
4067d000 4 rw--- 0000000000011000 0fe:00000 libkwalletclient.so.1.0.0
4067e000 4 rw--- 000000004067e000 000:00000 [ anon ]
4067f000 2148 r-x-- 0000000000000000 0fe:00000 libkdecore.so.4.2.0
40898000 64 rw--- 0000000000219000 0fe:00000 libkdecore.so.4.2.0
408a8000 8 rw--- 00000000408a8000 000:00000 [ anon ]
... (trimmed) ...
mapped: 25404K writeable/private: 2432K shared: 0K

I cut out a lot of the output; the rest is similar to what is shown. Even without the complete output, we can see some very interesting things. One important thing to note about the output is that each shared library is listed twice; once for its code segment and once for its data segment. The code segments have a mode of "r-x--", while the data is set to "rw---". The Kbytes, Mode, and Mapping columns are the only ones we will care about, as the rest are unimportant to the discussion.

If you go through the output, you will find that the lines with the largest Kbytes number are usually the code segments of the included shared libraries (the ones that start with "lib" are the shared libraries). What is great about that is that they are the ones that can be shared between processes. If you factor out all of the parts that are shared between processes, you end up with the "writeable/private" total, which is shown at the bottom of the output. This is what can be considered the incremental cost of this process, factoring out the shared libraries. Therefore, the cost to run this instance of KEdit (assuming that all of the shared libraries were already loaded) is around 2 megabytes. That is quite a different story from the 14 or 25 megabytes that ps reported.

What does it all mean?
The moral of this story is that process memory usage on Linux is a complex matter; you can't just run ps and know what is going on. This is especially true when you deal with programs that create a lot of identical children processes, like Apache. ps might report that each Apache process uses 10 megabytes of memory, when the reality might be that the marginal cost of each Apache process is 1 megabyte of memory. This information becomes critial when tuning Apache's MaxClients setting, which determines how many simultaneous requests your server can handle (although see one of my past postings for another way of increasing Apache's performance).

It also shows that it pays to stick with one desktop's software as much as possible. If you run KDE for your desktop, but mostly use Gnome applications, then you are paying a large price for a lot of redundant (but different) shared libraries. By sticking to just KDE or just Gnome apps as much as possible, you reduce your overall memory usage due to the reduced marginal memory cost of running new KDE or Gnome applications, which allows Linux to use more memory for other interesting things (like the file cache, which speeds up file accesses immensely).

Wednesday 24 October 2007

kde initial decoration - kpersonalizer

You can decorate your KDE very easily when you first activate it. All this is depending on the command of "kpersonalizer". Namely, when you want to change the look and feel rapidly, while not tweak hundreds of KDE options, just run it in konsole (terminal).

Stop Gnome Keyring Prompt For A Password

Keyring in Gnome.
clipped from www.ossgeeks.co.uk

What is Gnome Keyring Manager

GNOME keyring manager stores passwords such as WEP into an encrypted format that can be used over and over again when required by the user.

Bring on Libpam-Keyring

There is hope yet! :-) the libpam-keyring library can stop GNOME Keyring-manager prompting for a password when you access your protected wireless network. Install libpam-keyring by doing the following command in the terminal:-

sudo apt-get install libpam-keyring

Open the the gdm file:-

gksudo gedit /etc/pam.d/gdm

Add the following line to the end:-

@include common-pamkeyring

Save the file and exit. I should also point out that your GNOME Keyring-manager password MUST be the same as your log on (root). To ensure this go to the GNOME Keyring-manager at the “System > Administration” menu and delete your keyring, so nothing exists and reboot. You should now see no password prompt for your wireless network ;-).

Monday 22 October 2007

packages needed for Linux

Wine

libdvdcss2
w32codecs

ubuntu-restricted-extras (this one can solve mp3 and other third party stuff)
amarok (this will install needed codecs for mp3:libxine,
gstreamer0.10-ffmpeg)

xine(totem-xine)

nautilus-open -terminal

ndiswrapper

libpam-gnome-keyring(when the user login, make the keyringmanager unlocked)

stardict

vnc

konquer/opera

gedit-plugins(a lot of plugins for c/c++/java/latex etc.)

lyx(for latex and other formal document writing)

lynx(command-line web browser)
cmus/music123(command-line music player, sometime the mcop directory is needed to be created manually by ''mkdir -p $HOME/.kde/socket-$HOSTNAME/mcop'')

#####################
eclipse(+cdt,pydev)

texmaker(+texlive-latex)

build-essential
gcj

firestarter(firewall management program)

Chinese

envy (for graphical cards installation)

######################
samba(smbpasswd -a user, here this user must exist in the system users database)

gnome-rdp



Friday 19 October 2007

ndiswrapper in Ubuntu Gutsy

Ndiswrapper, a windows driver simulation for linux, in Ubuntu Gutsy seems there is a bug about automatically loaded when you did all the commands like this:

sudo apt-get install ndiswrapper
sudo ndiswrapper -i XXXXX.inf #installation of the drivers
sudo modprobe ndiswrapper

In Ubuntu Feisty 7.04, When you finish these commands, the light on your pcmcia wireless card will be turned on, and restart your computer, the wireless card will be loaded automatically when Ubuntu booting. But Gutsy not.

Nothing happened, unless you run:

sudo modprobe ndiswrapper


No worries, here are two methods to solve it.

1. put "ndiswrapper" in the /etc/modules.

P.S., some wireless
pcmcia card using prism54 will be loaded automatically without ndiswrapper by Ubuntu, you can stop it by this:

Put "blacklist prism54" in the /etc/modprobe.d/blacklist.

2. Just run the command "sudo ndiswrapper -ma", which will write the relative module to /etc/modprobe.d/, same effect with above.

Repositories in Ubuntu 7.10

# deb cdrom:[Kubuntu 7.10 _Gutsy Gibbon_ - Release i386 (20071016.1)]/ gutsy main restricted
# See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to
# newer versions of the distribution.

deb http://gb.archive.ubuntu.com/ubuntu/ gutsy main restricted
deb-src http://gb.archive.ubuntu.com/ubuntu/ gutsy main restricted

## Major bug fix updates produced after the final release of the
## distribution.
deb http://gb.archive.ubuntu.com/ubuntu/ gutsy-updates main restricted
deb-src http://gb.archive.ubuntu.com/ubuntu/ gutsy-updates main restricted

## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
## team, and may not be under a free licence. Please satisfy yourself as to
## your rights to use the software. Also, please note that software in
## universe WILL NOT receive any review or updates from the Ubuntu security
## team.
deb http://gb.archive.ubuntu.com/ubuntu/ gutsy universe
deb-src http://gb.archive.ubuntu.com/ubuntu/ gutsy universe
deb http://gb.archive.ubuntu.com/ubuntu/ gutsy-updates universe
deb-src http://gb.archive.ubuntu.com/ubuntu/ gutsy-updates universe

## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
## team, and may not be under a free licence. Please satisfy yourself as to
## your rights to use the software. Also, please note that software in
## multiverse WILL NOT receive any review or updates from the Ubuntu
## security team.
deb http://gb.archive.ubuntu.com/ubuntu/ gutsy multiverse
deb-src http://gb.archive.ubuntu.com/ubuntu/ gutsy multiverse
deb http://gb.archive.ubuntu.com/ubuntu/ gutsy-updates multiverse
deb-src http://gb.archive.ubuntu.com/ubuntu/ gutsy-updates multiverse

## Uncomment the following two lines to add software from the 'backports'
## repository.
## N.B. software from this repository may not have been tested as
## extensively as that contained in the main release, although it includes
## newer versions of some applications which may provide useful features.
## Also, please note that software in backports WILL NOT receive any review
## or updates from the Ubuntu security team.
deb http://gb.archive.ubuntu.com/ubuntu/ gutsy-backports main restricted universe multiverse
deb-src http://gb.archive.ubuntu.com/ubuntu/ gutsy-backports main restricted universe multiverse

## Uncomment the following two lines to add software from Canonical's
## 'partner' repository. This software is not part of Ubuntu, but is
## offered by Canonical and the respective vendors as a service to Ubuntu
## users.
deb http://archive.canonical.com/ubuntu/ gutsy partner
deb-src http://archive.canonical.com/ubuntu/ gutsy partner

deb http://security.ubuntu.com/ubuntu/ gutsy-security main restricted
deb-src http://security.ubuntu.com/ubuntu/ gutsy-security main restricted
deb http://security.ubuntu.com/ubuntu/ gutsy-security universe
deb-src http://security.ubuntu.com/ubuntu/ gutsy-security universe
deb http://security.ubuntu.com/ubuntu/ gutsy-security multiverse
deb-src http://security.ubuntu.com/ubuntu/ gutsy-security multiverse
#################################################
# http://medibuntu.org/
# sudo wget http://www.medibuntu.org/sources.list.d/gutsy.list -O /etc/apt/sources.list.d/medibuntu.list
# the public key:
# sudo wget -q http://packages.medibuntu.org/medibuntu-key.gpg -O- | sudo apt-key add - && sudo apt-get update

deb http://repository.debuntu.org/ gutsy multiverse
# deb-src http://repository.debuntu.org/ gutsy multiverse
# sudo wget http://repository.debuntu.org/GPG-Key-chantra.txt -O- | sudo apt-key add -

deb http://dl.google.com/linux/deb/ stable non-free
# sudo wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
# Or goto http://www.google.com/linuxrepositories/apt.html to download the key, then install by using synaptic

# deb http://ftp.de.debian.org/debian/ sid main
## sudo gpg --keyserver wwwkeys.eu.pgp.net --recv-keys 07DC563D1F41B907
## sudo apt-key add ~/.gnupg/pubring.gpg

Thursday 18 October 2007

Nokia unveils latest Linux tablet

clipped from news.zdnet.co.uk

The tablet — which includes no cellular connectivity, but does sport Wi-Fi and Bluetooth — is the third such device Nokia has produced in the past two years, as part of its drive to reposition the company's handsets as "multimedia computers" rather than mobile phones.

Nokia announced the tablet, which runs on the company's Maemo Linux operating system, at the Web 2.0 Summit in San Francisco.

The N810 will come with Skype and a Mozilla-based browser pre-installed and, unlike Nokia's other tablets, will come with a slide-out keyboard and integrated GPS — a feature Nokia expects will eventually feature on all its phones.

Feature

The device will ship from mid-November in some territories, for around US$479 (£234).

Despite the inclusion of new features, one expected improvement is yet to appear — WiMax connectivity. Nokia has already committed to launching WiMax-enabled products from next year and has previously hinted that the Linux tablet is in line for the connectivity upgrade.

Wednesday 17 October 2007

run System (Shell) command from the program

1. In C/C++ program
----------

In this short code snippet I will show you how to execute system commands like ping or nslookup or format c: ;-). The function we will use is rather intended to be used in textconsole based applications. But you could also use it in other programs.

That is our 'magic' function. You have to include stdlib.h to use it.

int system( const char *command );

command is a string that holds the app's name with optional arguments. It is used like on the commandline. The good thing is that the text output that the application produces will be shown in your textconsole. You could now use it to program your own shell! Nice, isn't it? The return-value will be same as the the return-value of the system command only if there was an error, then it will be -1. Here's a little example:

#include .h>
#include .h>

int main()
{
cout << "Executing ping..." << style="color: rgb(255, 0, 0);">"ping localhost");
cout << "Ping is done. I am done too. Let's shutdown and go for a drink."
<<>

This simple code snippet outputs some text and then starts ping with argument localhost. The ouput of ping will be shown in your textconsole and it will be the same as if you run it on the shell.



2. In Java program (quoted from:http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=1)
--------------------

As part of the Java language, the java.lang package is implicitly imported into every Java program. This package's pitfalls surface often, affecting most programmers. This month, I'll discuss the traps lurking in the Runtime.exec() method.

Pitfall 4: When Runtime.exec() won't

The class java.lang.Runtime features a static method called getRuntime(), which retrieves the current Java Runtime Environment. That is the only way to obtain a reference to the Runtime object. With that reference, you can run external programs by invoking the Runtime class's exec() method. Developers often call this method to launch a browser for displaying a help page in HTML.

There are four overloaded versions of the exec() command:

  • public Process exec(String command);
  • public Process exec(String [] cmdArray);
  • public Process exec(String command, String [] envp);
  • public Process exec(String [] cmdArray, String [] envp);


For each of these methods, a command -- and possibly a set of arguments -- is passed to an operating-system-specific function call. This subsequently creates an operating-system-specific process (a running program) with a reference to a Process class returned to the Java VM. The Process class is an abstract class, because a specific subclass of Process exists for each operating system.

You can pass three possible input parameters into these methods:

  1. A single string that represents both the program to execute and any arguments to that program
  2. An array of strings that separate the program from its arguments
  3. An array of environment variables


Pass in the environment variables in the form name=value. If you use the version of exec() with a single string for both the program and its arguments, note that the string is parsed using white space as the delimiter via the StringTokenizer class.

Stumbling into an IllegalThreadStateException

The first pitfall relating to Runtime.exec() is the IllegalThreadStateException. The prevalent first test of an API is to code its most obvious methods. For example, to execute a process that is external to the Java VM, we use the exec() method. To see the value that the external process returns, we use the exitValue() method on the Process class. In our first example, we will attempt to execute the Java compiler (javac.exe):

Listing 4.1 BadExecJavac.java

import java.util.*;
import java.io.*;
public class BadExecJavac
{
public static void main(String args[])
{
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("javac");
int exitVal = proc.exitValue();
System.out.println("Process exitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
}
}


A run of BadExecJavac produces:

E:\classes\com\javaworld\jpitfalls\article2>java BadExecJavac
java.lang.IllegalThreadStateException: process has not exited
at java.lang.Win32Process.exitValue(Native Method)
at BadExecJavac.main(BadExecJavac.java:13)


If an external process has not yet completed, the exitValue() method will throw an IllegalThreadStateException; that's why this program failed. While the documentation states this fact, why can't this method wait until it can give a valid answer?

A more thorough look at the methods available in the Process class reveals a waitFor() method that does precisely that. In fact, waitFor() also returns the exit value, which means that you would not use exitValue() and waitFor() in conjunction with each other, but rather would choose one or the other. The only possible time you would use exitValue() instead of waitFor() would be when you don't want your program to block waiting on an external process that may never complete. Instead of using the waitFor() method, I would prefer passing a boolean parameter called waitFor into the exitValue() method to determine whether or not the current thread should wait. A boolean would be more beneficial because exitValue() is a more appropriate name for this method, and it isn't necessary for two methods to perform the same function under different conditions. Such simple condition discrimination is the domain of an input parameter.

Therefore, to avoid this trap, either catch the IllegalThreadStateException or wait for the process to complete.

Now, let's fix the problem in Listing 4.1 and wait for the process to complete. In Listing 4.2, the program again attempts to execute javac.exe and then waits for the external process to complete:

Listing 4.2 BadExecJavac2.java

import java.util.*;
import java.io.*;
public class BadExecJavac2
{
public static void main(String args[])
{
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("javac");
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
}
}


Unfortunately, a run of BadExecJavac2 produces no output. The program hangs and never completes. Why does the javac process never complete?

Why Runtime.exec() hangs

The JDK's Javadoc documentation provides the answer to this question:



Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock.



Is this just a case of programmers not reading the documentation, as implied in the oft-quoted advice: read the fine manual (RTFM)? The answer is partially yes. In this case, reading the Javadoc would get you halfway there; it explains that you need to handle the streams to your external process, but it does not tell you how.

Another variable is at play here, as is evident by the large number of programmer questions and misconceptions concerning this API in the newsgroups: though Runtime.exec() and the Process APIs seem extremely simple, that simplicity is deceiving because the simple, or obvious, use of the API is prone to error. The lesson here for the API designer is to reserve simple APIs for simple operations. Operations prone to complexities and platform-specific dependencies should reflect the domain accurately. It is possible for an abstraction to be carried too far. The JConfig library provides an example of a more complete API to handle file and process operations (see Resources below for more information).

Now, let's follow the JDK documentation and handle the output of the javac process. When you run javac without any arguments, it produces a set of usage statements that describe how to run the program and the meaning of all the available program options. Knowing that this is going to the stderr stream, you can easily write a program to exhaust that stream before waiting for the process to exit. Listing 4.3 completes that task. While this approach will work, it is not a good general solution. Thus, Listing 4.3's program is named MediocreExecJavac; it provides only a mediocre solution. A better solution would empty both the standard error stream and the standard output stream. And the best solution would empty these streams simultaneously (I'll demonstrate that later).

Listing 4.3 MediocreExecJavac.java

import java.util.*;
import java.io.*;
public class MediocreExecJavac
{
public static void main(String args[])
{
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("javac");
InputStream stderr = proc.getErrorStream();
InputStreamReader isr = new InputStreamReader(stderr);
BufferedReader br = new BufferedReader(isr);
String line = null;
System.out.println("");
while ( (line = br.readLine()) != null)
System.out.println(line);
System.out.println("
");
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
}
}


A run of MediocreExecJavac generates:

E:\classes\com\javaworld\jpitfalls\article2>java MediocreExecJavac

Usage: javac
where includes:
-g Generate all debugging info
-g:none Generate no debugging info
-g:{lines,vars,source} Generate only some debugging info
-O Optimize; may hinder debugging or enlarge class files
-nowarn Generate no warnings
-verbose Output messages about what the compiler is doing
-deprecation Output source locations where deprecated APIs are used
-classpath Specify where to find user class files
-sourcepath Specify where to find input source files
-bootclasspath Override location of bootstrap class files
-extdirs Override location of installed extensions
-d Specify where to place generated class files
-encoding Specify character encoding used by source files
-target Generate class files for specific VM version

Process exitValue: 2


So, MediocreExecJavac works and produces an exit value of 2. Normally, an exit value of 0 indicates success; any nonzero value indicates an error. The meaning of these exit values depends on the particular operating system. A Win32 error with a value of 2 is a "file not found" error. That makes sense, since javac expects us to follow the program with the source code file to compile.

Thus, to circumvent the second pitfall -- hanging forever in Runtime.exec() -- if the program you launch produces output or expects input, ensure that you process the input and output streams.

Assuming a command is an executable program

Under the Windows operating system, many new programmers stumble upon Runtime.exec() when trying to use it for nonexecutable commands like dir and copy. Subsequently, they run into Runtime.exec()'s third pitfall. Listing 4.4 demonstrates exactly that:

Listing 4.4 BadExecWinDir.java

import java.util.*;
import java.io.*;
public class BadExecWinDir
{
public static void main(String args[])
{
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("dir");
InputStream stdin = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(stdin);
BufferedReader br = new BufferedReader(isr);
String line = null;
System.out.println("");
while ( (line = br.readLine()) != null)
System.out.println(line);
System.out.println("
");
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
}
}


A run of BadExecWinDir produces:

E:\classes\com\javaworld\jpitfalls\article2>java BadExecWinDir
java.io.IOException: CreateProcess: dir error=2
at java.lang.Win32Process.create(Native Method)
at java.lang.Win32Process.(Unknown Source)
at java.lang.Runtime.execInternal(Native Method)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at BadExecWinDir.main(BadExecWinDir.java:12)


As stated earlier, the error value of 2 means "file not found," which, in this case, means that the executable named dir.exe could not be found. That's because the directory command is part of the Windows command interpreter and not a separate executable. To run the Windows command interpreter, execute either command.com or cmd.exe, depending on the Windows operating system you use. Listing 4.5 runs a copy of the Windows command interpreter and then executes the user-supplied command (e.g., dir).

Listing 4.5 GoodWindowsExec.java

import java.util.*;
import java.io.*;
class StreamGobbler extends Thread
{
InputStream is;
String type;

StreamGobbler(InputStream is, String type)
{
this.is = is;
this.type = type;
}

public void run()
{
try
{
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line=null;
while ( (line = br.readLine()) != null)
System.out.println(type + ">" + line);
} catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}
public class GoodWindowsExec
{
public static void main(String args[])
{
if (args.length <>");
System.exit(1);
}

try
{
String osName = System.getProperty("os.name" );
String[] cmd = new String[3];
if( osName.equals( "Windows NT" ) )
{
cmd[0] = "cmd.exe" ;
cmd[1] = "/C" ;
cmd[2] = args[0];
}
else if( osName.equals( "Windows 95" ) )
{
cmd[0] = "command.com" ;
cmd[1] = "/C" ;
cmd[2] = args[0];
}

Runtime rt = Runtime.getRuntime();
System.out.println("Execing " + cmd[0] + " " + cmd[1]
+ " " + cmd[2]);
Process proc = rt.exec(cmd);
// any error message?
StreamGobbler errorGobbler = new
StreamGobbler(proc.getErrorStream(), "ERROR");

// any output?
StreamGobbler outputGobbler = new
StreamGobbler(proc.getInputStream(), "OUTPUT");

// kick them off
errorGobbler.start();
outputGobbler.start();

// any error???
int exitVal = proc.waitFor();
System.out.println("ExitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
}
}


Running GoodWindowsExec with the dir command generates:

E:\classes\com\javaworld\jpitfalls\article2>java GoodWindowsExec "dir *.java"
Execing cmd.exe /C dir *.java
OUTPUT> Volume in drive E has no label.
OUTPUT> Volume Serial Number is 5C5F-0CC9
OUTPUT>
OUTPUT> Directory of E:\classes\com\javaworld\jpitfalls\article2
OUTPUT>
OUTPUT>10/23/00 09:01p 805 BadExecBrowser.java
OUTPUT>10/22/00 09:35a 770 BadExecBrowser1.java
OUTPUT>10/24/00 08:45p 488 BadExecJavac.java
OUTPUT>10/24/00 08:46p 519 BadExecJavac2.java
OUTPUT>10/24/00 09:13p 930 BadExecWinDir.java
OUTPUT>10/22/00 09:21a 2,282 BadURLPost.java
OUTPUT>10/22/00 09:20a 2,273 BadURLPost1.java
... (some output omitted for brevity)
OUTPUT>10/12/00 09:29p 151 SuperFrame.java
OUTPUT>10/24/00 09:23p 1,814 TestExec.java
OUTPUT>10/09/00 05:47p 23,543 TestStringReplace.java
OUTPUT>10/12/00 08:55p 228 TopLevel.java
OUTPUT> 22 File(s) 46,661 bytes
OUTPUT> 19,678,420,992 bytes free
ExitValue: 0


Running GoodWindowsExec with any associated document type will launch the application associated with that document type. For example, to launch Microsoft Word to display a Word document (i.e., one with a .doc extension), type:

>java GoodWindowsExec "yourdoc.doc"


Notice that GoodWindowsExec uses the os.name system property to determine which Windows operating system you are running -- and thus determine the appropriate command interpreter. After executing the command interpreter, handle the standard error and standard input streams with the StreamGobbler class. StreamGobbler empties any stream passed into it in a separate thread. The class uses a simple String type to denote the stream it empties when it prints the line just read to the console.

Thus, to avoid the third pitfall related to Runtime.exec(), do not assume that a command is an executable program; know whether you are executing a standalone executable or an interpreted command. At the end of this section, I will demonstrate a simple command-line tool that will help you with that analysis.

It is important to note that the method used to obtain a process's output stream is called getInputStream(). The thing to remember is that the API sees things from the perspective of the Java program and not the external process. Therefore, the external program's output is the Java program's input. And that logic carries over to the external program's input stream, which is an output stream to the Java program.

Runtime.exec() is not a command line

One final pitfall to cover with Runtime.exec() is mistakenly assuming that exec() accepts any String that your command line (or shell) accepts. Runtime.exec() is much more limited and not cross-platform. This pitfall is caused by users attempting to use the exec() method to accept a single String as a command line would. The confusion may be due to the fact that command is the parameter name for the exec() method. Thus, the programmer incorrectly associates the parameter command with anything that he or she can type on a command line, instead of associating it with a single program and its arguments. In listing 4.6 below, a user tries to execute a command and redirect its output in one call to exec():

Listing 4.6 BadWinRedirect.java

import java.util.*;
import java.io.*;
// StreamGobbler omitted for brevity
public class BadWinRedirect
{
public static void main(String args[])
{
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("java jecho 'Hello World' > test.txt");
// any error message?
StreamGobbler errorGobbler = new
StreamGobbler(proc.getErrorStream(), "ERROR");

// any output?
StreamGobbler outputGobbler = new
StreamGobbler(proc.getInputStream(), "OUTPUT");

// kick them off
errorGobbler.start();
outputGobbler.start();

// any error???
int exitVal = proc.waitFor();
System.out.println("ExitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
}
}


Running BadWinRedirect produces:

E:\classes\com\javaworld\jpitfalls\article2>java BadWinRedirect
OUTPUT>'Hello World' > test.txt
ExitValue: 0


The program BadWinRedirect attempted to redirect the output of an echo program's simple Java version into the file test.txt. However, we find that the file test.txt does not exist. The jecho program simply takes its command-line arguments and writes them to the standard output stream. (You will find the source for jecho in the source code available for download in Resources.) In Listing 4.6, the user assumed that you could redirect standard output into a file just as you could on a DOS command line. Nevertheless, you do not redirect the output through this approach. The incorrect assumption here is that the exec() method acts like a shell interpreter; it does not. Instead, exec() executes a single executable (a program or script). If you want to process the stream to either redirect it or pipe it into another program, you must do so programmatically, using the java.io package. Listing 4.7 properly redirects the standard output stream of the jecho process into a file.

Listing 4.7 GoodWinRedirect.java

import java.util.*;
import java.io.*;
class StreamGobbler extends Thread
{
InputStream is;
String type;
OutputStream os;

StreamGobbler(InputStream is, String type)
{
this(is, type, null);
}
StreamGobbler(InputStream is, String type, OutputStream redirect)
{
this.is = is;
this.type = type;
this.os = redirect;
}

public void run()
{
try
{
PrintWriter pw = null;
if (os != null)
pw = new PrintWriter(os);

InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line=null;
while ( (line = br.readLine()) != null)
{
if (pw != null)
pw.println(line);
System.out.println(type + ">" + line);
}
if (pw != null)
pw.flush();
} catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}
public class GoodWinRedirect
{
public static void main(String args[])
{
if (args.length <>");
System.exit(1);
}

try
{
FileOutputStream fos = new FileOutputStream(args[0]);
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("java jecho 'Hello World'");
// any error message?
StreamGobbler errorGobbler = new
StreamGobbler(proc.getErrorStream(), "ERROR");

// any output?
StreamGobbler outputGobbler = new
StreamGobbler(proc.getInputStream(), "OUTPUT", fos);

// kick them off
errorGobbler.start();
outputGobbler.start();

// any error???
int exitVal = proc.waitFor();
System.out.println("ExitValue: " + exitVal);
fos.flush();
fos.close();
} catch (Throwable t)
{
t.printStackTrace();
}
}
}


Running GoodWinRedirect produces:

E:\classes\com\javaworld\jpitfalls\article2>java GoodWinRedirect test.txt
OUTPUT>'Hello World'
ExitValue: 0


After running GoodWinRedirect, test.txt does exist. The solution to the pitfall was to simply control the redirection by handling the external process's standard output stream separately from the Runtime.exec() method. We create a separate OutputStream, read in the filename to which we redirect the output, open the file, and write the output that we receive from the spawned process's standard output to the file. Listing 4.7 completes that task by adding a new constructor to our StreamGobbler class. The new constructor takes three arguments: the input stream to gobble, the type String that labels the stream we are gobbling, and the output stream to which we redirect the input. This new version of StreamGobbler does not break any of the code in which it was previously used, as we have not changed the existing public API -- we only extended it.

Since the argument to Runtime.exec() is dependent on the operating system, the proper commands to use will vary from one OS to another. So, before finalizing arguments to Runtime.exec() and writing the code, quickly test the arguments. Listing 4.8 is a simple command-line utility that allows you to do just that.

Here's a useful exercise: try to modify TestExec to redirect the standard input or standard output to a file. When executing the javac compiler on Windows 95 or Windows 98, that would solve the problem of error messages scrolling off the top of the limited command-line buffer.

Listing 4.8 TestExec.java

import java.util.*;
import java.io.*;
// class StreamGobbler omitted for brevity
public class TestExec
{
public static void main(String args[])
{
if (args.length < cmd =" args[0];" rt =" Runtime.getRuntime();" proc =" rt.exec(cmd);" errorgobbler =" new" outputgobbler =" new" exitval =" proc.waitFor();">


Running TestExec to launch the Netscape browser and load the Java help documentation produces:

E:\classes\com\javaworld\jpitfalls\article2>java TestExec "e:\java\docs\index.html"
java.io.IOException: CreateProcess: e:\java\docs\index.html error=193
at java.lang.Win32Process.create(Native Method)
at java.lang.Win32Process.(Unknown Source)
at java.lang.Runtime.execInternal(Native Method)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at TestExec.main(TestExec.java:45)


Our first test failed with an error of 193. The Win32 error for value 193 is "not a valid Win32 application." This error tells us that no path to an associated application (e.g., Netscape) exists, and that the process cannot run an HTML file without an associated application.

Therefore, we try the test again, this time giving it a full path to Netscape. (Alternately, we could add Netscape to our PATH environment variable.) A second run of TestExec produces:

E:\classes\com\javaworld\jpitfalls\article2>java TestExec
"e:\program files\netscape\program\netscape.exe e:\java\docs\index.html"
ExitValue: 0


This worked! The Netscape browser launches, and it then loads the Java help documentation.

One additional improvement to TestExec would include a command-line switch to accept input from standard input. You would then use the Process.getOutputStream() method to pass the input to the spawned external program.

To sum up, follow these rules of thumb to avoid the pitfalls in Runtime.exec():

  1. You cannot obtain an exit status from an external process until it has exited
  2. You must immediately handle the input, output, and error streams from your spawned external process
  3. You must use Runtime.exec() to execute programs
  4. You cannot use Runtime.exec() like a command line

Files about Latex

There are also files that are created by LaTeX2e, the .aux file, the .toc file and the .bib file. The .aux (auxiliary) file is where LaTeX stores all the information about the counters (like section numbers), footnotes, bibliography entries, reference marks, and anything else that LaTeX may need to keep track of. This file is written over whenever a file is typeset by LaTeX. Whenever a document is typeset LaTeX reads this file to get the information it need, and writes to it after typesetting is completed. This is why changes in the counters will not take effect until LaTeX is run twice, because the .aux file is not up to date the first time. The .bib file is where all the bibliography information is kept. You can either make this file yourself, or you can use BibTeX to create the file. The .toc file contains all the information needed to create the Table of Contents. This file is created when LaTeX sees the command \tableofcontents, and the section names, numbers and page numbers are all read from the .aux file.

Friday 12 October 2007

make and Makefile in Linux

Well, now that you're learned how to use lots of source files, objects, and libraries to build large programs, how are you ever going to manage them all? How will you remember all the commands and options you'll need to remember to build it? Fortunately, you don't have to. DJGPP (and most development systems) include a program that manages your projects for you. If you are using RHIDE, this is the project definition, which is managed through RHIDE's menus (and is documented in RHIDE's documentation). There is also a stand-alone program called make that keeps track of how to make your program from the sources (hence the name). The file that contains the instructions for make is called a makefile (and is usually called makefile).

The syntax of a makefile is deceptively simple (GNU make includes a lot of extensions, functions, and tricks that can make makefiles almost as complex as your source). You can have two kinds of commands (besides comments) - variable definitions and rules. A variable definition can be a simple thing, like this:

OBJECTS = main.o foo.o bar.o math3d.o graphics.o
They can get pretty complicated also (see the make reference manual) but for now we'll stick to the simple cases.

The more interesting command is a rule, which tells make what it's making, what it's made from, and how to make it. Consider this example:

main.o : main.c
gcc -c main.c

Note that the line with gcc is prefixed by a tab - a real tab character, not eight spaces! Many DOS editors will insert eight spaces when you hit the TAB key, instead of just inserting a tab. If you get a "missing separator" error, that's what happened to you.

Anyway, in this example rule there are three parts: The target, the dependencies, and the commands (well, command). The target is the thing that we want to make. In this case, we want to make the file main.o. Next, after the target (and the colon, which separates targets from dependencies), we list the depenencies - the files that the target depends on. In this case, main.o needs to be rebuilt whenever main.c changes, so we list main.c as a dependency. The last part of the rule is the command that make should run in order to make the target from the depenencies. In this case, we list the gcc command to compile main.c into main.o. Note that you may list as many commands as required, as long as you don't leave a blank line and all commands start with a tab.

Makefiles may (and often do) contain many variables and rules. Here's a Makefile we'd use for our sample program:

main.exe : main.o foo.o
gcc main.o foo.o -o main.exe

main.o : main.c
gcc -c main.c

foo.o : foo.c
gcc -c foo.c

To use this makefile, you run the make program, like this:

C:\SRC> make

Pretty simple, yes? The make program knows to look for a file called Makefile or makefile. If you used a different name, run it like this: "make -f makefile.djg".

Note that make always starts with the first rule it sees, in this case the one for main.exe, and tries to build that first. As it find dependencies, it checks to see if those need to be updated. Based on the makefile above, make will run these three commands the first time you call it:

gcc -c main.c
gcc -c foo.c
gcc main.o foo.o -o main.exe

However, if you then edit foo.c and run make again, it will only run these commands:

gcc -c foo.c
gcc main.o foo.o -o main.exe

It doesn't recompile main.c because it knows that it doesn't have to. In a big project, that could save you a lot of time.

Our example makefile didn't use any variables. Let's include some, to see if it help us out:

CC = gcc
CFLAGS = -g -O2
OBJECTS = main.o foo.o

main.exe : $(OBJECTS)
$(CC) $(CFLAGS) $(OBJECTS) -o main.exe

main.o : main.c
$(CC) $(CFLAGS) -c main.c

foo.o : foo.c
$(CC) $(CFLAGS) -c foo.c

This makefile looks a lot like the old makefile, except that a lot of the commands have been replaced with variable substitutions. What make does is replace the variables with their variables in the target, dependency, and command sections of the rules. That lets you specify some things in one place to make it easier to maintain. In our example, we use $(CC) to specify the compiler, so we could set it to something else if we wanted to without having to change the whole makefile.

Here's another trick that GNU make can let you do. In the above makefile, we had to include the rule for compiling sources into objects twice - once for each source file. That could get tiresome when we have dozens of sources, so let's define a pattern instead. This pattern will be used whenever make needs to compile any source:

%.o : %.c
$(CC) $(CFLAGS) -c $<

Here, we have used the percent (%) character to denote that part of the target and dependency that matches whatever the pattern is used for, and the $< is a special variable (imaging it like $(<)) that means "whatever the depencies are". Another useful variable is $@, which means "the target". Our Makefile now looks like this:

CC = gcc
CFLAGS = -g -O2
OBJECTS = main.o foo.o

main.exe : $(OBJECTS)
$(CC) $(CFLAGS) $(OBJECTS) -o main.exe

%.o : %.c
$(CC) $(CFLAGS) -c $<

Now, if we need to add more source files, we only have to update the line that defines the OBJECTS variable!

Note that make is pretty smart about a lot of things already, like how to build object files. In our above example, we could have left out the last rule completely! The fact that we chose CC and CFLAGS as names was no coincidence, since those are the variables that make's built-in rules use. To see a list of all the built-in rules, consult the make documentation or run "make -p"

The reference manual for make (run "info make") contains many more examples and nifty tricks for building makefiles, but this section covered the bare minimum that you'll need to know to manage your projects with make.

Saturday 6 October 2007

Eclipse Setting for C/C++


Eclipse for C/C++ enables a lot of features personalized.

I am quite used to use STANDARD MAKE Project, within which I can decide when and how to compile the C/C++ code.

The fig. is what favorite setting for C/C++ make project, the essential is:

g++ ${resource_name} -g -o ${project_name}.

Here, -g for g++ is debug information option, it can be omitted. I prefer Cygwin as default provider of compilers, when you finish Cygwin, everything is done, much convenient for use compared with Mingw.
Right click in the code file you are working on, select "Create Make Target", you will find that everything is there, you don't need to modify anything in the setting. Just run the new created Build command by double click from the view of Make Project from Windows>Show View, here we are, your executable comes out.

The amazing thing is not only for C/C++, even more, it can be used in composing latex stuff. When you create the new project, latex one but you want to make it in the C/C++ Standard Make environment, modify the setting command to:

latex ${resource_name}
or pdflatex ${resource_name}

Now when you create new Build patch from your file, you can decide when and how your compile the latex files. Very personalized.

My photo
London, United Kingdom
twitter.com/zhengxin

Facebook & Twitter