Tech Today

One of my clients today asked me if I could send him some code that would effectively open a new browser window to a fixed height and width, with no menu bar.

This is a basic problem that might be worth knowing in the future. So here is the solution:

First you need to add this code between the <head></head> tags of your HTML document:

<script type="text/javascript">
function openpopup(address){
window.open(address,"","fullscreen=no,toolbar=no,status=no,
menubar=no,scrollbars=no,resizable=no,width=500,height=500");
}
</script>

Then you will need to create a link somewhere in your document. Like so:

<a href="javascript: openpopup('http://www.google.com')"> Click here to open the page in a new window. </a>

And vola! You are now able to open links in a new browser window! Now, this solution will also work for local html documents, but I believe it is always better practice to put the full URLs in anyways. Hope this solution works for you and enjoy!

Advertisements

REQUIRES:

Compiling a [C] program in Linux

POSIX Message passing is supported in Unix, Linux, Mac OS X and many more.

The example shown here was derived in Ubuntu 9.04 using the Jaunty Jackalope Kernel Version: 2.6.28-11.

Okay, so first question what exactly is POSIX Message passing and why should I use it?

Well, POSIX stands for “Portable Operating System Interface for Unix” and it is a collection of standards governed by the IEEE.

Message passing is all about processes being able to communicate and synchronize with one another. Why do process need to communicate with one another? Well sometimes processes hold data that other processes may need. This doesn’t just hold true for process though, think about the World Wide Web. Computers need to be able to communicate with one another all the time, so wouldn’t it be nice to have some kind of mechanism in place that demonstrates that functionality? Yeah, I thought so too.

Well here is an example of processes communication utilizing the POSIX API. Think of it as like a client – server relationship; if that helps…

Overview:

Basically four external process will be communicating with a central process relaying temperature data back and forth. The goal here is to get all the processes to have the same temperature. Once that happens the central process will send a message indicating the system is stable and the processes can print out their final temp and end. Until the system is stable the external and central processes will continue to calculate new temperatures and relay them back and forth. [NOTE]: The four external processes are only aware of the central process, but the central process is aware of all the processes.

This starts by utilizing msgget(); This function will request a message queue ID using the mailbox name provided or create one if not existent previously.

Then use msgsnd(); to relay a message to a particular mailbox and use msgrcv(); the get a message from a mailbox.

First the “server side” code:

#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define CENTRAL_MAILBOX 1200    //Central Mailbox number 
#define NUM_PROCESSES 4           //Total number of external processes

struct {
long priority;         //message priority
int temp;             //temperature
int pid;                //process id
int stable;            //boolean for temperature stability
} msgp, cmbox;

//MAIN function
int main(int argc, char *argv[]) {

   //Validate that a temperature was given via the command line
   if(argc != 2) {
      printf("USAGE: Too few arguments --./central.out Temp");
      exit(0);
   }

   printf("\nStarting Server...\n");

   //Set up local variables
   int i,result,length,status;             //counter for loops
   int uid = 0;                               //central process ID
   int initTemp = atoi(argv[1]);        //starting temperature
   int msqid[NUM_PROCESSES];       //mailbox IDs for all processes
   int unstable = 1;          //boolean to denote temp stability
   int tempAry[NUM_PROCESSES];   //array of process temperatures

   //Create the Central Servers Mailbox
   int msqidC = msgget(CENTRAL_MAILBOX, 0600 | IPC_CREAT);

   //Create the mailboxes for the other processes and store their IDs
   for(i = 1; i <= NUM_PROCESSES; i++){
      msqid[(i-1)] = msgget((CENTRAL_MAILBOX + i), 0600 | IPC_CREAT);
   }

   //Initialize the message to be sent
   msgp.priority = 1;
   msgp.pid = uid;
   msgp.temp = initTemp;
   msgp.stable = 1;

   /* The length is essentially the size 
       of the structure minus sizeof(mtype) */
   length = sizeof(msgp) - sizeof(long);

   //While the processes have different temperatures
   while(unstable == 1){
      int sumTemp = 0;        //sum up the temps as we loop
      int stable = 1;            //stability trap

      // Get new messages from the processes
      for(i = 0; i < NUM_PROCESSES; i++){
         result = msgrcv( msqidC, &cmbox, length, 1, 0);

         /* If any of the new temps are different from the old temps
             then we are still unstable. Set the new temp to the
             corresponding process ID in the array */
         if(tempAry[(cmbox.pid - 1)] != cmbox.temp) {
            stable = 0;
            tempAry[(cmbox.pid - 1)] = cmbox.temp;
         }

         //Add up all the temps as we go for the temperature algorithm
         sumTemp += cmbox.temp;
      }

      //When all the processes have the same temp twice:
      // 1) Break the loop
      // 2) Set the messages stable field to stable
      if(stable){
         printf("\Temperature Stabilized: %d\n", msgp.temp);
         unstable = 0;
         msgp.stable = 0;
      }
      else { //Calc a new temp and set the temp field in the message
         int newTemp = (2 * msgp.temp + sumTemp) / 6;
         msgp.temp = newTemp;
      }

      /* Send a new message to all processes 
          to inform of new temp or stability */
      for(i = 0; i < NUM_PROCESSES; i++){
         result = msgsnd( msqid[i], &msgp, length, 0);
      }
   }

   printf("\nShutting down Server...\n");

   //Remove the mailbox
   status = msgctl(msqidC, IPC_RMID, 0);

   //Validate nothing when wrong when trying to remove mailbox
   if(status != 0){
      printf("\nERROR closing mailbox\n");
   }
}

Next the “client side” external processes:

#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define CENTRAL_MAILBOX 1200    //Central Mailbox number

struct {
long priority;        //message priority
int temp;            //temperature
int pid;               //process id
int stable;          //boolean for temperature stability
} msgp, cmbox;

//MAIN function
int main(int argc, char *argv[]) {

   /* Validate that a temperature and a Unique 
       process ID was given via the command  */
   if(argc != 3) {
      printf("USAGE: Too few arguments --./central.out Temp UID");
      exit(0);
   }

   //Setup local variables
   int unstable = 1;
   int result, length, status;
   int initTemp = atoi(argv[1]);
   int uid = atoi(argv[2]);

   //Create the Central Servers Mailbox
   int msqidC = msgget(CENTRAL_MAILBOX, 0600 | IPC_CREAT);

   //Create the mailbox for this process and store it's IDs
   int msqid = msgget((CENTRAL_MAILBOX + uid), 0600 | IPC_CREAT);

   //Initialize the message to be sent
   cmbox.priority = 1;
   cmbox.pid = uid;
   cmbox.temp = initTemp;
   cmbox.stable = 1;

   /* The length is essentially the size of 
       the structure minus sizeof(mtype) */
   length = sizeof(msgp) - sizeof(long);

   //While all the processes have different temps
   while(unstable == 1){
      //Send the current temp to the central server
      result = msgsnd( msqidC, &cmbox, length, 0);

      //Wait for a new message from the central server
      result = msgrcv( msqid, &msgp, length, 1, 0);

      //If the new message indicates all the processes have the same temp
      //break the loop and print out the final temperature
      if(msgp.stable == 0) {
         unstable = 0;
         printf("\nProcess %d Temp: %d\n", cmbox.pid, cmbox.temp);
      }
      else { //otherwise calculate the new temp and store it
         int newTemp = (cmbox.temp * 3 + 2 * msgp.temp) / 5;
         cmbox.temp = newTemp;
      }
   }

   //Remove the mailbox
   status = msgctl(msqid, IPC_RMID, 0);

   //Validate nothing when wrong when trying to remove mailbox
   if(status != 0){
      printf("\nERROR closing mailbox\n");
   }
}

START YOUR ENGINES:

Run each process in a separate terminal like so:

./external.out 100 1

./external.out 22 2

./external.out 50 3

./external.out 40 4

./central.out 60

OUTPUT:

lee@isis:~$ ./central.out 60

Starting Server...

Temperature Stabilized: 49

Shutting down Server...

lee@isis:~$ ./external.out 100 1

Process 1 Temp: 49

lee@isis:~$ ./external.out 22 2

Process 2 Temp: 49

lee@isis:~$ ./external.out 50 3

Process 3 Temp: 49

lee@isis:~$ ./external.out 40 4

Process 4 Temp: 49

Congratulations, you have just experienced process communication. Now, where can you take this mechanism from here?

REQUIRES:

Compiling a [C] program in Linux

Today we are going to add a custom “Hello World” system call to Ubuntu 9.04 Linux using the kernel version: 2.6.28-11.

First things first, we need to figure out how to get the source and build a custom kernel. Instructions for how to do this can be found in my previous post:

Compiling a UBUNTU Jaunty Jackalope Kernel

Ok, now that we know how to compile a shiny new custom kernel, we need to create our system call:

/* adding helloworld system call */
#include <linux/linkage.h>

asmlinkage int sys_helloworld() {
   printk(KERN_EMERG "Hello World!\n");
   return 0;
}

Now, I opted to add this to /usr/src/linux/kernel/sys.c. However, you can always create your own file and add it to the kernel’s makefile. If you decide to go down this route you are also going to need to #include <linux/kernel.h> to the code above; the file kernel/sys.c already includes that package.

Lets explain what’s going on here a little shall we?

asmlinkage: thats there to indicate the code is written in ‘C’ as oppose to C++

printk: is used to print out kernel log messages. These messages are stored in /var/log/syslog.

KERN_EMERG: is used for logging emergency messages; these usually happen before a crash. The Kernel has 8 different types of log levels, a few others are- KERN_DEBUG, KERN_ALERT, KERN_ERR

Alright, now that we have our system call we need to let the kernel know its there and can be used.

To do this we will have to modify a few files.

Modify /usr/src/linux/arch/x86/include/asm/unistd_32.h and add:

#define __NR_helloworld         333

to the list of system call numbers. This is the system calls unique identification number.

Modify /usr/src/linux/arch/x86/include/asm/syscalls.h and add:

/* X86_32 only */
/* kernel/sys.c */
asmlinkage int sys_helloworld();

under the “/* X86_32 only */” comment. This registers the system call.

Modify /usr/src/linux/arch/x86/kernel/syscall_table_32.h and add:

.long sys_helloworld           /* 333 */

to the bottom of the list. This also registers the system call.

Alright, now build your new modified kernel..this is going to take a while…

OK, SO 2 hours later…Install the new kernel and reboot.

Now we have to build a little c-program to use that shiny new system call right? *How Exciting!*

#include <sys/syscall.h>
#include <unistd.h>
#include <stdio.h>

#define __NR_helloworld        333    /* or     whatever you set it in unistd.h */

int helloworld() {
   return (int) syscall(__NR_helloworld);
};

main () {
   printf("The return code from the helloworld system call is %d\n", helloworld());
}

Compile it and lets see what happens!

Output [Command Line]:

lee@isis:~$ ./a.out
The return code from the helloworld system call is 0

Output [/var/log/syslog]:

May 14 23:19:02 isis kernel: [48397.527522] Hello World!

Exactly what we expected. Our program returned ‘0’ from the system call execution AND we have the output in the logs. YAY!

[NOTE]: Now, you may have issues with flushing the buffer at this step so you may have to trigger an event on the system like reset your wifi connection to actually see the print out in the log. However, having the newline at the end of the message is supposed to guarantee the flush.

Congratulations you just made your very own system call in your very own custom kernel. Mom would be so proud, if only she knew what a kernel or a system call was!

Enjoy! =)

current Kernel version: 2.6.28-11

In /usr/src get the source and build tools by typing:

sudo apt-get install linux-source kernel-package fakeroot ncurses-dev

Unpack the source by typing:

sudo bzip2 -d linux-source-2.6.28.tar.bz2
sudo tar xvf linux-source-2.6.28.tar

Make a sym link to the linux source code by typing:

ln -s linux-source-2.6.28 linux

Enter the source directory:

cd linux

Then we are going to make a clean package using the current configuration of the current kernel since it already figured everything out for you.

sudo make-kpkg clean
sudo cp /boot/config-`uname -r` ./.config

Make any changes you want to the kernel here:

sudo make menuconfig

sudo fakeroot make-kpkg --initrd --append-to-version=-lml kernel_image kernel_headers
[NOTE]:–append-to-version” will append a string to the version number; here I am using my initials “lml”. You’re going to want to do this to distinguish your kernel builds apart.

This will give us the header and image output in /usr/src. Issuing these commands will install your new custom kernel:

sudo dpkg -i linux-image-2.6.28.9lml_2.6.28.9lml-10.00.Custom_i386.deb
sudo dpkg -i linux-headers-2.6.28.9lml_2.6.28.9lml-10.00.Custom_i386.deb

As you can see my initials “lml” have been appended in two places.

This also installs the new kernel to grub so next time you boot you will be able to select it.

To edit the grub options:

sudo nano /boot/grub/menu.lst

So, today I am working on understanding how processes communicate in the Linux OS. This code example is written in C and compiled in Ubuntu 9.04 using the Jaunty Jackalope Kernel version 2.6.28-11.

This code specifically prints out the Fibonacci sequence.

The parent process creates and attaches a shared memory segment, forks a child process (remember the child process shares the resources of the parent) , waits for the child to finish, prints out the contents of the shared memory, and finally detaches and removes the shared memory segment.

The child process runs through the Fibonacci algorithm, inserts the resultant into the next available space in shared memory and prints out the resultant to standard output.

This example accepts input from the command line with basic error checking. You know, make sure two args have been provided, they are between the min and max limits of the program; the BASICS.

CODE:

#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define MAX_SEQUENCE 10 // Max values to store in shared memory
#define MIN_SEQUENCE 2  // Min value the user can enter

//shared memory:
// 1) holds an array of numbers
// 2) holds how many numbers are in the array
typedef struct {
int fib_seq[MAX_SEQUENCE];
int sequence_size;
} shared_data;

//MAIN function
int main(int argc, char *argv[]) {

pid_t pid;    //process ID
int segment_id; //Shared Memory ID
shared_data *mem; //Shared Memory Pointer

//check to validate atleast two arguments
if(argc != 2) {
printf(“USAGE ERROR: [0-9]\n”);
exit(0);
}

//validate the input is not larger then the MAX
if(atoi(argv[1]) > MAX_SEQUENCE) {
printf(“Max Input Size: %d\n”, MAX_SEQUENCE);
exit(0);
}

//validate the input is not smaller then the MIN
if(atoi(argv[1]) < MIN_SEQUENCE) {
printf(“Min Input Size: %d\n”, MIN_SEQUENCE);
exit(0);
}

// 1) create a new shared memory location ‘IPC_PRIVATE’
// 2) the size of our shared memory structure ‘sizeof(shared_data)’
// 3) Set Modes S_IRUSR and S_IWUSR so the owner can read and write to the shared memory ‘S_IRUSR|S_IWUSR’
segment_id = shmget(IPC_PRIVATE, sizeof(shared_data), S_IRUSR|S_IWUSR);

//attach the shared memory and get the pointer to the beginning location in memory
mem = (shared_data *) shmat(segment_id,NULL,0);

//set the size of the sequence to the argument that was passed in via command line
mem->sequence_size = atoi(argv[1]);

// fork a child process
pid = fork();

if(pid < 0) { /* error occured */
fprintf(stderr, “Fork Failed\n”);
return 1;
}
else if(pid == 0) { /* child process */
int counter = 0;
printf(“Child Fibonacci Sequence: “);

while(counter < mem->sequence_size) {
if(counter == 0){
//FIB of zero is always zero
mem->fib_seq[counter] = 0;
}
else if(counter == 1){
//FIB of one is always one
mem->fib_seq[counter] = 1;
}
else {
//The Fibonacci Sequence formula ‘R = fib(n-1) + fib(n-2)’
//The first two numbers in the sequence are always 0 and 1.
//To get a value in the sequence you will want to take the previous
//two numbers and add them together. For example:
// b + a = c
// [fib(d-1) = c] + [fib(d-2) = b] = R
// fib(0) = 0
// fib(1) = 1
// fib(2): 1 + 0 = 1
// fib(3): 1 + 1 = 2
// fib(4): 2 + 1 = 3
// fib(5): 3 + 2 = 5
// The next Fibonacci number in the sequence will be ‘8’
mem->fib_seq[counter] = mem->fib_seq[counter – 1] + mem->fib_seq[counter – 2];
}
printf(“%d “, mem->fib_seq[(counter)]);
counter++;
}
}
else { /* parent process */

/* parent will wait for the child process to complete */
wait(NULL);

//Print out shared memory
int count = 0;
printf(“\nParent Fibonacci Sequence: “);
while(count < mem->sequence_size){
printf(“%d “, mem->fib_seq[count]);
count++;
}

//detach shared memory
shmdt(mem);
//remove shared memory segment
shmctl(segment_id,IPC_RMID,NULL);
printf(“\nComplete\n”);
}

return 0;
}

output:


lee@isis:~$ ./a.out 0
Min Input Size: 2
lee@isis:~$ ./a.out 1
Min Input Size: 2
lee@isis:~$ ./a.out 2
Child Fibonacci Sequence: 0 1
Parent Fibonacci Sequence: 0 1
Complete
lee@isis:~$ ./a.out 3
Child Fibonacci Sequence: 0 1 1
Parent Fibonacci Sequence: 0 1 1
Complete
lee@isis:~$ ./a.out 4
Child Fibonacci Sequence: 0 1 1 2
Parent Fibonacci Sequence: 0 1 1 2
Complete
lee@isis:~$ ./a.out 5
Child Fibonacci Sequence: 0 1 1 2 3
Parent Fibonacci Sequence: 0 1 1 2 3
Complete