Showing posts with label linux. Show all posts
Showing posts with label linux. Show all posts

Wednesday, January 23, 2008

Really, really nice

Just a quick one today.

After my previous qemu post, I found this really cool article on how to debug the linux kernel itself running on the emulator. It even uses Eclipse CDT so you have a nice IDE while debugging the kernel code.

Great stuff...

Tuesday, January 22, 2008

Fork/exec while redirecting I/O

Here's a common problem in (POSIX) C applications: let's say you want to execute another application, but you want to redirect this application's standard I/O (i.e., stdin, stdout, stderr) to a file descriptor(s) of your choice. Perhaps you want to log the output to a file, or stream the application's input from a file you just created, or collect error messages (stderr) for parsing later.

The function below illustrates how to do this:

pid_t
exec_redirect(
const char *path, char *const args[],
int new_in, int new_out, int new_err
)
{

pid_t child;

// Fork new process
child = fork();

if (child == 0) {

// Child process

// Redirect standard input
if (new_in >= 0) {
close(STDIN_FILENO);
dup2(new_in, STDIN_FILENO);
}

// Redirect standard output
if (new_out >= 0) {
close(STDOUT_FILENO);
dup2(new_out, STDOUT_FILENO);
}

// Redirect standard error
if (new_err >= 0) {
close(STDERR_FILENO);
dup2(new_err, STDERR_FILENO);
}

// Execute the command
execv(path, args);
}

// Parent process
return child;

}

This function takes the parameters path and args which is the same as what you would normally pass to execv(3). In addition, there are three parameters, new_in, new_out, and new_err which are (optional) file descriptors where the new application's standard input, output, and error, respectively, will be redirected from/to. To make redirection optional, we specify that if the descriptor parameter is -1, then no redirection will take place.

So how do we use this? The code snippet below executes the command line /bin/myapp -l -p, with input redirected from in.txt, output redirected to out.txt, and error redirected to err.txt:

    ...
char *cmd = "/bin/myapp";
char *args[] = { "/bin/myapp", "-l", "-p", NULL };

in = open("in.txt", O_RDONLY);
out = open("out.txt", O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
err = open("err.txt", O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);

exec_redirect(cmd, args, in, out, err);
...

On a closing note, it's also probably a good idea to close() the file handles in the parent process, after exec_redirect(), just to prevent "inadvertently" accessing them while the child process is also doing the same. Yes, the pun was intended ;-)

[Update: fixed some typos]

Wednesday, December 12, 2007

Installing Ubuntu 7.04 Server on QEMU

I was able to install and run an Ubuntu 7.04 Linux (Server Edition) on a Windows XP host using QEMU. Installation was pretty straightforward, what required some extra research was getting the Linux guest OS to communicate with the host OS using TCP/IP.

Here are the steps:

Ubuntu Installation

1. Download and install QEMU for Windows

2. (Optional) Download and install KQEMU for Windows

This will greatly speed up the virtual machine running in QEMU.

3. You will also need to download the Ubuntu server .iso file.

4. Once these are ready, you can create the disk image that will be used by the virtual machine.

The command line below will create a disk image 3GB-large in the file ubuntu.img:

qemu-img.exe create ubuntu.img 3G

5. Boot the virtual machine with the Ubuntu .iso as CD-ROM drive

qemu.exe -cdrom ubuntu-7.04-server-i386.iso -boot d -m 256 -L . ubuntu.img

You should see a window with the Ubuntu installation screen.
Proceed with the installation as per normal.

After installation, you need to reboot with the disk image as boot disk. Just remove the -boot d option to do this.

qemu.exe -cdrom ubuntu-7.04-server-i386.iso -m 256 -L . ubuntu.img

Voila! A Linux box (with LAMP) right inside your Windows desktop.

Configuring the Network

There are a couple of ways to go about this, and it really depends on your network configuration (i.e., whether you use DHCP, whether you need to connect to the Internet, etc.). The steps below describe what I did in my set-up:

1. Download and install OpenVPN.

Actually you will just need the Tap-Win32 component, so you can go ahead and de-select the other components during installation.

2. After installation you will have a new "Local Area Connection" in your Network Settings folder. For convenience later, I suggest you rename this to something like tap0.

This interface will be used to connect to the guest OS. You can assign it an IP address, e.g. 192.168.1.1.

3. Boot the guest OS, but this time add the ff. parameters: -net nic -net tap,ifname=tap0

This will give the virtual machine a network interface, and connect that network interface to the host's tap0 interface.

4. After the Ubuntu server has booted, it should have an eth0 interface. You can assign an IP address to this using ifconfig.

$ ifconfig eth0 192.168.1.2

That's it. Your host OS and guest OS should have network connectivity! Try to ping each other. Your network should look like this:

192.168.1.2(eth0, linux) <----> 192.168.1.1(tap0, windows)

If you want to connect the linux box to the Internet then you can use the bridging function of Windows. I also suggest turning on the Samba server of the linux box so that transferring files between OSes will be very convenient.

Happy emulating!