Linux Shell Piping w/Shared Memory


 
Thread Tools Search this Thread
Top Forums Programming Linux Shell Piping w/Shared Memory
# 1  
Old 02-10-2017
Linux Linux Shell Piping w/Shared Memory

So I am pretty new to the linux environment, and I am trying to create a shell that uses multiple pipes, and I read online that piping using shared memory space is more efficient than using regular piping. However, I have zero clue how to use shared memory space with pipes. Has anyone done this already or can someone tinker with my current code to enable shared memory space? I'd like to implement this in other projects in the future so learning it would be helpful, and if you could provide an explanation of your function uses, that would be fantastic. Here is my piping code so far:

Code:
void launchProg(char **args, int background){	 
	 int err = -1;
	 
	 if((pid=fork())==-1){
		 printf("Child process could not be created\n");
		 return;
	 }
	 // pid == 0 implies the following code is related to the child process
	if(pid==0){
		// We set the child to ignore SIGINT signals (we want the parent
		// process to handle them with signalHandler_int)	
		signal(SIGINT, SIG_IGN);
		
		// We set parent=<pathname>/simple-c-shell as an environment variable
		// for the child
		setenv("parent",getcwd(currentDirectory, 1024),1);	
		
		// If we launch non-existing commands we end the process
		if (execvp(args[0],args)==err){
			printf("Command not found");
			kill(getpid(),SIGTERM);
		}
	 }
	 
	 if (background == 0){
		 waitpid(pid,NULL,0);
	 }else{
		 printf("Process created with PID: %d\n",pid);
	 }	 
}
 
void fileIO(char * args[], char* inputFile, char* outputFile, int option){
	 
	int err = -1;
	
	int fileDescriptor; // between 0 and 19, describing the output or input file
	
	if((pid=fork())==-1){
		printf("Child process could not be created\n");
		return;
	}
	if(pid==0){
		// Option 0: output redirection
		if (option == 0){
			// We open (create) the file truncating it at 0, for write only
			fileDescriptor = open(outputFile, O_CREAT | O_TRUNC | O_WRONLY, 0600); 
			// We replace de standard output with the appropriate file
			dup2(fileDescriptor, STDOUT_FILENO); 
			close(fileDescriptor);
		// Option 1: input and output redirection
		}else if (option == 1){
			// We open file for read only (it's STDIN)
			fileDescriptor = open(inputFile, O_RDONLY, 0600);  
			// We replace de standard input with the appropriate file
			dup2(fileDescriptor, STDIN_FILENO);
			close(fileDescriptor);
			// Same as before for the output file
			fileDescriptor = open(outputFile, O_CREAT | O_TRUNC | O_WRONLY, 0600);
			dup2(fileDescriptor, STDOUT_FILENO);
			close(fileDescriptor);		 
		}
		 
		setenv("parent",getcwd(currentDirectory, 1024),1);
		
		if (execvp(args[0],args)==err){
			printf("err");
			kill(getpid(),SIGTERM);
		}		 
	}
	waitpid(pid,NULL,0);
}


void pipeHandler(char * args[]){
	// File descriptors
	int filedes[2]; // pos. 0 output, pos. 1 input of the pipe
	int filedes2[2];
	
	int num_cmds = 0;
	
	char *command[256];
	
	pid_t pid;
	
	int err = -1;
	int end = 0;
	
	// Variables used for the different loops
	int i = 0;
	int j = 0;
	int k = 0;
	int l = 0;
	
	// First we calculate the number of commands (they are separated
	// by '|')
	while (args[l] != NULL){
		if (strcmp(args[l],"|") == 0){
			num_cmds++;
		}
		l++;
	}
	num_cmds++;
	
	while (args[j] != NULL && end != 1){
		k = 0;
		while (strcmp(args[j],"|") != 0){
			command[k] = args[j];
			j++;	
			if (args[j] == NULL){
				end = 1;
				k++;
				break;
			}
			k++;
		}
	        command[k] = NULL;
		j++;		
		
		if (i % 2 != 0){
			pipe(filedes); // for odd i
		}else{
			pipe(filedes2); // for even i
		}
		
		pid=fork();
		
		if(pid==-1){			
			if (i != num_cmds - 1){
				if (i % 2 != 0){
					close(filedes[1]); // for odd i
				}else{
					close(filedes2[1]); // for even i
				} 
			}			
			printf("Child process could not be created\n");
			return;
		}
		if(pid==0){
			if (i == 0){
				dup2(filedes2[1], STDOUT_FILENO);
			}

			else if (i == num_cmds - 1){
				if (num_cmds % 2 != 0){ // for odd number of commands
					dup2(filedes[0],STDIN_FILENO);
				}else{ // for even number of commands
					dup2(filedes2[0],STDIN_FILENO);
				}
			}else{ // for odd i
				if (i % 2 != 0){
					dup2(filedes2[0],STDIN_FILENO); 
					dup2(filedes[1],STDOUT_FILENO);
				}else{ // for even i
					dup2(filedes[0],STDIN_FILENO); 
					dup2(filedes2[1],STDOUT_FILENO);					
				} 
			}
			
			if (execvp(command[0],command)==err){
				kill(getpid(),SIGTERM);
			}		
		}
				
		if (i == 0){
			close(filedes2[1]);
		}
		else if (i == num_cmds - 1){
			if (num_cmds % 2 != 0){					
				close(filedes[0]);
			}else{					
				close(filedes2[0]);
			}
		}else{
			if (i % 2 != 0){					
				close(filedes2[0]);
				close(filedes[1]);
			}else{					
				close(filedes[0]);
				close(filedes2[1]);
			}
		}
				
		waitpid(pid,NULL,0);
				
		i++;	
	}
}
			
int commandHandler(char * args[]){
	int i = 0;
	int j = 0;
	
	int fileDescriptor;
	int standardOut;
	
	int aux;
	int background = 0;
	
	char *args_aux[256];
	
	while ( args[j] != NULL){
		if ( (strcmp(args[j],">") == 0) || (strcmp(args[j],"<") == 0) || (strcmp(args[j],"&") == 0)){
			break;
		}
		args_aux[j] = args[j];
		j++;
	}
	
	// 'exit' command quits the shell
	if(strcmp(args[0],"exit") == 0) exit(0);
	// 'pwd' command prints the current directory
 	else if (strcmp(args[0],"pwd") == 0){
		if (args[j] != NULL){
			// If we want file output
			if ( (strcmp(args[j],">") == 0) && (args[j+1] != NULL) ){
				fileDescriptor = open(args[j+1], O_CREAT | O_TRUNC | O_WRONLY, 0600); 
				// We replace de standard output with the appropriate file
				standardOut = dup(STDOUT_FILENO);
				dup2(fileDescriptor, STDOUT_FILENO); 
				close(fileDescriptor);
				printf("%s\n", getcwd(currentDirectory, 1024));
				dup2(standardOut, STDOUT_FILENO);
			}
		}else{
			printf("%s\n", getcwd(currentDirectory, 1024));
		}
	} 
 	// 'clear' command clears the screen
	else if (strcmp(args[0],"clear") == 0) system("clear");
	// 'cd' command to change directory
	else if (strcmp(args[0],"cd") == 0) changeDirectory(args);
	// 'environ' command to list the environment variables
	else if (strcmp(args[0],"environ") == 0){
		if (args[j] != NULL){
			// If we want file output
			if ( (strcmp(args[j],">") == 0) && (args[j+1] != NULL) ){
				fileDescriptor = open(args[j+1], O_CREAT | O_TRUNC | O_WRONLY, 0600); 
				// We replace de standard output with the appropriate file
				standardOut = dup(STDOUT_FILENO);
				dup2(fileDescriptor, STDOUT_FILENO); 
				close(fileDescriptor);
				manageEnviron(args,0);
				dup2(standardOut, STDOUT_FILENO);
			}
		}else{
			manageEnviron(args,0);
		}
	}
	// 'setenv' command to set environment variables
	else if (strcmp(args[0],"setenv") == 0) manageEnviron(args,1);
	// 'unsetenv' command to undefine environment variables
	else if (strcmp(args[0],"unsetenv") == 0) manageEnviron(args,2);
	else{

		while (args[i] != NULL && background == 0){

			if (strcmp(args[i],"&") == 0){
				background = 1;

			}else if (strcmp(args[i],"|") == 0){
				pipeHandler(args);
				return 1;

			}else if (strcmp(args[i],"<") == 0){
				aux = i+1;
				if (args[aux] == NULL || args[aux+1] == NULL || args[aux+2] == NULL ){
					printf("Not enough input arguments\n");
					return -1;
				}else{
					if (strcmp(args[aux+1],">") != 0){
						printf("Usage: Expected '>' and found %s\n",args[aux+1]);
						return -2;
					}
				}
				fileIO(args_aux,args[i+1],args[i+3],1);
				return 1;
			}

			else if (strcmp(args[i],">") == 0){
				if (args[i+1] == NULL){
					printf("Not enough input arguments\n");
					return -1;
				}
				fileIO(args_aux,NULL,args[i+1],0);
				return 1;
			}
			i++;
		}

		launchProg(args_aux,background);
	}
return 1;
}

Moderator's Comments:
Mod Comment Moved to Programming

Last edited by jim mcnamara; 02-11-2017 at 09:20 AM..
# 2  
Old 02-11-2017
Welcome the the UNIX forums.

You do not use pipes with shared memory, necessarily. You are reading and writing in memory to your own process memory, part of which is shared among processes. So each child process is reading and writing it's own memory, too.

What you are talking about is IPC. Interprocess communication. Pipes are one method, shared memory segments are another. Pipes use physical files on disk, shared memory transfers data between processes using a segment of memory both processes 'own' and can read and usually write.

You need to do some reading, the help you need is beyond the scope of these forums.
If you get stuck we can help. This tutorial is written in an offhand conversational way, most people enjoy reading it.

Beej's Guide to Unix IPC

More formal:
6 Linux Interprocess Communications

Last edited by jim mcnamara; 02-11-2017 at 09:23 AM..
This User Gave Thanks to jim mcnamara For This Post:
Login or Register to Ask a Question

Previous Thread | Next Thread

9 More Discussions You Might Find Interesting

1. Programming

Shared library with acces to shared memory.

Hello. I am new to this forum and I would like to ask for advice about low level POSIX programming. I have to implement a POSIX compliant C shared library. A file will have some variables and the shared library will have some functions which need those variables. There is one special... (5 Replies)
Discussion started by: iamjag
5 Replies

2. Red Hat

Unable to remove shared memory in Redhat Linux

unable to remove shared memory using ipcrm -m in linux $ ipcs -m ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00000000 32768 root 644 80 2 0x00000000 65537 root ... (4 Replies)
Discussion started by: LinuxLearner
4 Replies

3. Red Hat

Shared memory in linux

Hello, I am using Linux os. $ df -k /dev/shm Filesystem 1K-blocks Used Available Use% Mounted on tmpfs 2023256 1065000 958256 53% /dev/shm $ Based on my google this, it is shared memory. What is this shared memory and where exactly it is used? Can you... (5 Replies)
Discussion started by: govindts
5 Replies

4. Red Hat

about shared memory space in Linux !

Dear Friends , I am confused about shared memory in Linux . plz look @ the below output : $ df -h Filesystem Size Used Avail Use% Mounted on /dev/sda1 126G 61G 59G 52% / tmpfs 1.7G 0 1.7G 0% /dev/shm Here , I see that every time... (1 Reply)
Discussion started by: shipon_97
1 Replies

5. Programming

Shared memory for shared library

I am writing a shared library in Linux (but compatible with other UNIXes) and I want to allow multiple instances to share a piece of memory -- 1 byte is enough. What's the "best" way to do this? I want to optimize for speed and portability. Obviously, I'll have to worry about mutual exclusion. (0 Replies)
Discussion started by: otheus
0 Replies

6. Programming

Shared memory in shared library

I need to create a shared library to access an in memory DB. The DB is not huge, but big enough to make it cumbersome to carry around in every single process using the shared library. Luckily, it is pretty static information, so I don't need to worry much about synchronizing the data between... (12 Replies)
Discussion started by: DreamWarrior
12 Replies

7. Programming

memory sharing - not shared memory -

hi, this is the problem: i want to swap a linked list between 4 processes (unrelated), is there any way i can do that just by sending a pointer to a structure? //example typedef struct node { int x; char c; struct node *next; } node; or i should send the items ( x,c ) by... (9 Replies)
Discussion started by: elzalem
9 Replies

8. Linux

all about shared memory

Hi all :confused: , I am new to unix.I have been asked to implement shared memory in user's mode.What does this mean?What is the difference it makes in kernel mode and in users mode?What are the advantages of this impemenation(user's mode)? And also i would like to know why exactly shared... (0 Replies)
Discussion started by: vijaya2006
0 Replies

9. UNIX for Advanced & Expert Users

Shared memory shortage but lots of unused memory

I am running HP-UX B.11.11. I'm increasing a parameter for a database engine so that it uses more memory to buffer the disk drive (to speed up performance). I have over 5GB of memory not being used. But when I try to start the DB with the increased buffer parameter I get told. "Not... (1 Reply)
Discussion started by: cjcamaro
1 Replies
Login or Register to Ask a Question