Creating shared memory in C - c

I created following method in C to create a shared memory segment to store counter value. But I can't store data in this segment.When I try to print the value of the counter it gives me a garbage value.Whats wrong with this code?
CreateCounter()
{
key = ftok(".",'B');
shmCntid = shmget(key,COUNTER_SIZE,IPC_CREAT|0666);
if(shmCntid == -1 )
{
perror("shmget");
exit(1);
}
else
{
printf("Creating new Sahred memory sement\n");
cntPtr = shmat(shmCntid,0,0);
if(cntPtr == -1 )
{
perror("shmat");
exit(1);
}
}
}
This method is called inside the main method as follows.
int *cntPtr;
int rowCnt;
sem_t s;
sem_t c;
sem_t r;
int main(int argc, int *argv[])
{
int pid, pid2, pid3, i;
CreateBuf1();
CreateBuf2();
CreateCounter();
GetInput(argv[1],*buf1Ptr);
sem_init(&c, 0, 1);
sem_init(&r, 0, 1);
sem_init(&s, 0, 1);
for( i = 0 ; i < 9; i++)
{
pid = fork();
if(pid < 0)
{
printf("Fork error !\n");
}
else if (pid == 0)
break;
}
if(pid < 0)
{
printf("Fork error !\n");
}
else if (pid == 0)
{
sem_wait(&r);
Grp1 (i,i);
cntPtr+=rowCnt;
sleep(1);
sem_post(&r);
sem_post(&c);
exit(0);
}
else
{
wait(NULL);
}
pid2 = fork();
if(pid2 < 0)
{
printf("Fork error !\n");
}
else if (pid2 == 0)
{
sem_wait(&c);
Grp2(9);
cntPtr+=colCnt;
sleep(1);
sem_post(&c);
exit(0);
}
else
{
wait(NULL);
}
// This space is to print the values..............
shmctl(shmBuf1id,IPC_RMID,0);
shmctl(shmBuf2id,IPC_RMID,0);
shmctl(shmCntid,IPC_RMID,0);
return 0;
}

Related

Close pipes get Bad file descriptor

Here is the code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
int main(int argc, char **argv) {
int num = 2;
pid_t pid;
int i;
int p1[num][2], p2[num][2];
for (i = 0; i < num; i++) {
if (pipe(p1[i]) == -1) {
perror("pipe");
exit(1);
}
if (pipe(p2[i]) == -1) {
perror("pipe");
exit(1);
}
}
for (i = 0; i < num; i++) {
if ((pid = fork()) == 0) {
if (close(p1[i][1]) != 0) {
perror("close");
exit(1);
}
if (close(p2[i][0]) != 0) {
perror("close");
exit(1);
}
printf("%d\n", getpid());
exit(0);
} else if (pid > 0) {
if (close(p1[i][0]) != 0) {
perror("close");
exit(1);
}
if (close(p2[i][1]) != 0) {
perror("close");
exit(1);
}
continue;
} else {
perror("fork");
exit(1);
}
}
for (i = 0; i < num; i++) {
if (close(p1[i][0]) != 0) {
perror("close1"); // <----error
}
if (close(p1[i][1]) != 0) {
perror("close");
}
if (close(p2[i][0]) != 0) {
perror("close");
}
if (close(p2[i][1]) != 0) {
perror("close2"); // <----error
}
}
for (i = 0; i < num; i++) {
if (wait(NULL) == -1) {
perror("wait");
exit(1);
}
}
return 0;
}
When I run this, it gives me this output
close1: Bad file descriptor
close2: Bad file descriptor
close1: Bad file descriptor
close2: Bad file descriptor
8798
8799
What I'm trying to do is to create two 2D array of pipes and fork num times.
The creating and running are working well, but some pipes can't close.
It seems that p1[i][0] and p2[i][1] are never closer properly.
The reason you're getting the EBADFD is you're attempting to close the same file descriptor twice.
I added a print statement in this first snippet of code to show/track what file descriptor is being closed. If you compile and run this you'll see that the error message appears right after you try to close the descriptor for a second time.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
int main(int argc, char **argv) {
int num = 1;
pid_t pid;
int i;
int p1[num][2], p2[num][2];
for (i = 0; i < num; i++) {
if (pipe(p1[i]) == -1) {
perror("pipe");
exit(1);
}
if (pipe(p2[i]) == -1) {
perror("pipe");
exit(1);
}
}
for (i = 0; i < num; i++) {
if ((pid = fork()) == 0) {
printf("Child closing: Pipe1 %d End %d\n", i, 1);
if (close(p1[i][1]) != 0) {
perror("close");
exit(1);
}
printf("Child closing: Pipe2 %d End %d\n", i, 1);
if (close(p2[i][0]) != 0) {
perror("close");
exit(1);
}
printf("%d\n", getpid());
exit(0);
} else if (pid > 0) {
printf("Parent closing: Pipe1 %d End %d\n", i, 0);
if (close(p1[i][0]) != 0) {
perror("close");
exit(1);
}
printf("Parent closing: Pipe1 %d End %d\n", i, 1);
if (close(p2[i][1]) != 0) {
perror("close");
exit(1);
}
continue;
} else {
perror("fork");
exit(1);
}
}
for (i = 0; i < num; i++) {
printf("Closing: Pipe1: %d End: %d\n", i, 0);
if (close(p1[i][0]) != 0) {
perror("close1"); // <----error
}
printf("Closing: Pipe1: %d End: %d\n", i, 1);
if (close(p1[i][1]) != 0) {
perror("close");
}
printf("Closing: Pipe2: %d End: %d\n", i, 0);
if (close(p2[i][0]) != 0) {
perror("close");
}
printf("Closing: Pipe2: %d End: %d\n", i, 1);
if (close(p2[i][1]) != 0) {
perror("close2"); // <----error
}
}
for (i = 0; i < num; i++) {
if (wait(NULL) == -1) {
perror("wait");
exit(1);
}
}
return 0;
}
Check for the pid and close the ends that weren't closed inside your first loop. This code assumes you are reading and writing on a specific pipe depending on the child's/parent's need. You may need to adjust to however your use case dictates:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
int main(int argc, char **argv) {
int num = 1;
pid_t pid;
int i;
int p1[num][2], p2[num][2];
for (i = 0; i < num; i++) {
if (pipe(p1[i]) == -1) {
perror("pipe");
exit(1);
}
if (pipe(p2[i]) == -1) {
perror("pipe");
exit(1);
}
}
for (i = 0; i < num; i++) {
if ((pid = fork()) == 0) {
if (close(p1[i][1]) != 0) {
perror("close");
exit(1);
}
if (close(p2[i][0]) != 0) {
perror("close");
exit(1);
}
printf("%d\n", getpid());
exit(0);
} else if (pid > 0) {
if (close(p1[i][0]) != 0) {
perror("close");
exit(1);
}
if (close(p2[i][1]) != 0) {
perror("close");
exit(1);
}
continue;
} else {
perror("fork");
exit(1);
}
}
for (i = 0; i < num; i++) {
if (pid == 0) {
if (close(p1[i][0]) != 0) {
perror("close1");
}
if (close(p2[i][1]) != 0) {
perror("close");
}
} else {
if (close(p1[i][1]) != 0) {
perror("close");
}
if (close(p2[i][0]) != 0) {
perror("close2");
}
}
}
for (i = 0; i < num; i++) {
if (wait(NULL) == -1) {
perror("wait");
exit(1);
}
}
return 0;
}

Multiple Pipe Recursive Handing in c

I want to handle multiple pipes in c via a recursive function. I could not figure it what is wrong. Whether I did not hook up the pipes properly or I left some process hanging. Please give some advice.
Assume: token[0] = "ls"; token[1] = "|"; token[2] = "sort"; token[3] = "|"; token[4] = "more";
int pipeExecution(char *token[]) {
int isPipe = 0;
int fds[2] = {0};
pid_t pid;
for (int i = 0; token[i] != NULL; i++) {
if (strcmp(token[i], "|") == 0) {
isPipe = 1;
token[i] = NULL;
if (pipe(fds) < 0) {
perror("Can not pipe\n");
exit(EXIT_FAILURE);
}
pid = fork();
if (pid < 0) {
perror("Can not fork() **1\n");
exit(EXIT_FAILURE);
} else {
if (pid > 0) {
pid = fork();
if (pid < 0) {
perror("Can not fork() **2\n");
exit(EXIT_FAILURE);
} else {
if (pid > 0) { // parent
wait(NULL);
} else { // child 2 - excuse the command after a "|"
close(fds[1]); // does not write to pipe
if (dup2(fds[0], STDIN_FILENO) < 0) {
perror("Can not dup2()\n");
exit(EXIT_FAILURE);
}
printf("execute tokens after |\n");
pipeExecution(token + (i + 1));
}
}
} else { // child 1 - excuse the command before a "|"
printf("execute tokens before |\n");
close(fds[0]); // does not read from pipe
if (dup2(fds[1], STDOUT_FILENO) < 0) {
perror("Can not dup2()\n");
exit(EXIT_FAILURE);
}
execvp(token[0], token);
}
}
break;
}
}
if (isPipe == 0) {
perror(token[0]);
pid = fork();
if (pid < 0) {
perror("Can not fork()\n");
exit(EXIT_FAILURE);
}
if (pid > 0) {
wait(NULL);
} else {
execvp(token[0], token);
}
}
return 0;
}

why this linux pseudo terminal program doesn't work?

Master reads input from stdin and writes to pty-master, slave reads input from pty-slave and writes to stdout.
But this code/program seems doesn't work.
The Master writes to pty-master is OK, but the slave hungs when reads from pty-slave.
anyone can help me? thx in advance.
#include <assert.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
/*
* copy from apue
*/
int ptym_open(char *pts_name, int pts_namesz)
{
char *ptr;
int fdm, err;
if ((fdm = posix_openpt(O_RDWR)) < 0) {
assert(0);
return -1;
}
if (grantpt(fdm) < 0) {
assert(0);
return -1;
}
if (unlockpt(fdm) < 0) {
assert(0);
return -1;
}
if ((ptr = ptsname(fdm)) == NULL) {
assert(0);
return -1;
}
strncpy(pts_name, ptr, pts_namesz);
pts_name[pts_namesz - 1] = 0;
printf("pts_name:%s\n", pts_name);
return fdm;
}
int ptys_open(char *pts_name)
{
int fds;
if ((fds = open(pts_name, O_RDWR)) < 0) {
return -1;
}
return fds;
}
int pty_fork(int *ptrfdm, char *slave_name, int slave_namesz)
{
int fdm, fds;
pid_t pid;
char pts_name[1024];
if ((fdm = ptym_open(pts_name, sizeof(pts_name))) < 0) {
assert(0);
return -1;
}
if (slave_name != NULL) {
strncpy(slave_name, pts_name, slave_namesz);
slave_name[slave_namesz - 1] = 0;
}
if ((pid = fork()) < 0) {
assert(0);
return -1;
} else if (pid == 0) {
if (setsid() < 0) {
assert(0);
}
if ((fds = ptys_open(pts_name)) < 0) {
assert(0);
}
close(fdm);
if (dup2(fds, STDIN_FILENO) != STDIN_FILENO) {
assert(0);
}
//if (dup2(fds, STDOUT_FILENO) != STDOUT_FILENO) {
// assert(0);
//}
//if (dup2(fds, STDERR_FILENO) != STDERR_FILENO) {
// assert(0);
//}
if ((fds != STDIN_FILENO) && (fds != STDOUT_FILENO) && (fds != STDERR_FILENO)) {
close(fds);
}
return 0;
} else {
*ptrfdm = fdm;
return pid;
}
}
int loop(int ptym)
{
pid_t pid;
int nread;
#define BUFFSIZE 512
char buf[BUFFSIZE];
if ((pid = fork()) < 0) {
assert(0);
} else if (pid == 0) {
while (1) {
if ((nread = read(STDIN_FILENO, buf, BUFFSIZE)) < 0) {
int errr = errno;
printf("%s\n", strerror(errr));
assert(0);
} else if (nread = 0) {
break;
}
if (write(ptym, buf, nread) != nread) {
int errr = errno;
printf("%s\n", strerror(errr));
assert(0);
}
fsync(ptym);
}
exit(0); // child
}
while (1) {
if ((nread = read(ptym, buf, BUFFSIZE)) <= 0) {
printf("%d break read\n", getpid());
break;
}
if (write(STDOUT_FILENO, buf, nread) != nread) {
assert(0);
}
}
}
int main(void)
{
int fdm;
char slave_name[1024];
pid_t pid = pty_fork(&fdm, slave_name, sizeof(slave_name));
if (pid < 0) {
assert(0);
} else if (pid == 0) {
int nread;
char buf[1024];
while(1){
if ((nread = read(STDIN_FILENO, buf, 3)) < 0) {
break;
}
printf("buf:%s\n", buf);
}
} else {
printf("child:%d#%s\n", pid, slave_name);
loop(fdm);
}
return 0;
}
Besides opening the pseudo-terminal, you have to initialize it (something referred to as line discipline). I don't see any of that in your example. You could compare with luit, which does do this (look for instance at the openTty function in sys.c).
Further reading:
Notes 7: Terminal I/O
Writing a Kernel Line Discipline
What are the responsibilities of each Pseudo-Terminal (PTY) component (software, master side, slave side)?

Only first line gets printed from a file. Using forks and pipes

I'm trying to make this print multiple lines of a file with spaces replaced with * and everything translated to uppercase. This is supposed be done through pipes and forks. Why is it that only the first line gets printed.
void writer(int inpipe)
{
char read_msg[BUFFER_SIZE];
pid_t pid;
int fd[2];
read(inpipe, read_msg, BUFFER_SIZE);
printf("%s\n",read_msg);
return;
}
void p2(int inpipe)
{
char read_msg[BUFFER_SIZE];
pid_t pid;
int fd[2];
if(pipe(fd) == -1) {
perror("Pipe error");
return;
}
pid = fork();
if(pid<0) { //error
perror("Fork Failed");
return;
}
else if(pid==0) { //child
close(fd[1]);
writer(fd[0]);
close(fd[0]);
return;
}
else { //parent, p2()
read(inpipe, read_msg, BUFFER_SIZE);
int i = 0;
while (read_msg[i] != '\0') {
read_msg[i] = toupper(read_msg[i]);
i++;
}
close(fd[0]);
write(fd[1],read_msg,(unsigned long)(strlen(read_msg)+1));
close(fd[1]);
}
return;
}
void p1(int inpipe)
{
char read_msg[BUFFER_SIZE];
pid_t pid;
int fd[2];
if(pipe(fd) == -1) {
perror("Pipe error");
return;
}
pid = fork();
if(pid<0) { //error
perror("Fork Failed");
return;
}
else if(pid==0) { //child
close(fd[1]);
p2(fd[0]);
close(fd[0]);
return;
}
else { //parent, p1()
read(inpipe, read_msg, BUFFER_SIZE);
int i = 0;
while (read_msg[i] != '\0') {
if ((read_msg[i] == ' '))
read_msg[i] = '*';
i++;
}
//printf("%s\n",read_msg);
close(fd[0]);
write(fd[1],read_msg,(unsigned long)(strlen(read_msg)+1));
close(fd[1]);
}
return;
}
int main(int argc, char **argv) {
pid_t pid;
int fd[2];
if(pipe(fd) == -1) {
perror("Pipe error");
return 1;
}
pid = fork();
if(argv[1] != NULL) {
char const* const fileName = argv[1];
FILE* file = fopen(fileName, "r");
char line[BUFFER_SIZE];
while (fgets(line, sizeof(line), file)){
if(pid<0) { //error
perror("Fork Failed");
return 1;
}
else if(pid==0) { //child
close(fd[1]);
p1(fd[0]);
close(fd[0]);
}
else { //parent, main(), reader
//reading from the file and put it into the pipe[1]
close(fd[0]);
write(fd[1],line,strlen(line)+1);
close(fd[1]);
}
}
}
else
printf("No file detected.\n");
return EXIT_SUCCESS;
}

Linux Shell Pipeline Execution

I am trying to implement a basic linux shell with support for pipelining. However, my code seems to hang or just not execute programs and I can't figure out why.
if (list_empty(&job_list))
job_index = 1;
bool dopipe = false;
if (list_size(&pipeline->commands) > 1)
dopipe = true;
esh_signal_sethandler(SIGCHLD, signal_handler);
esh_signal_block(SIGCHLD);
setpgid(0, 0);
pipeline->pgrp = getpgid(0);
pipeline->jid = job_index++;
list_push_back(&job_list, &pipeline->elem);
bool background = pipeline->bg_job;
pid_t pid;
if ( (pid = fork()) == 0)
{
//Child
if (pipeline->bg_job)
setpgid(0, 0);
int oldpipe[2];
int newpipe[2];
int count = 0;
int size = list_size(&pipeline->commands);
struct list_elem * current_job;
printf("SIZE: %zu\n", list_size(&pipeline->commands));
for (current_job = list_begin(&pipeline->commands); current_job != list_tail(&pipeline->commands); current_job = list_next(current_job))
{
if (count < size)
pipe(newpipe);
pid_t fpid = fork();
printf("fpid: %d\n", (int)fpid);
if (fpid == 0)
{
//Child
printf("Executing Child\n");
if (count > 0)
{
//prev command exists
dup2(oldpipe[0], 0);
close(oldpipe[0]);
close(oldpipe[1]);
}
if (count < size - 1)
{
//next command exists
close(newpipe[0]);
dup2(newpipe[1], 1);
close(newpipe[1]);
}
esh_command* cmd = list_entry(current_job, struct esh_command, elem);
printf("Running: %s %s\n", cmd->argv[0], cmd->argv[1]);
if (execvp(cmd->argv[0], cmd->argv) < 0)
esh_sys_fatal_error("Program Does Not Exist\n");
}
else
{
//Parent
//*
int status = 0;
if (waitpid(fpid, &status, 0) < 0)
esh_sys_fatal_error("Could not fork pipe\n");
//*/
printf("Parent\n");
if (count > 0)
{
//prev command exists
close(oldpipe[0]);
close(oldpipe[1]);
}
if (count < size - 1)
{
//next command exists
oldpipe[0] = newpipe[0];
oldpipe[1] = newpipe[1];
}
printf("End of Parent\n");
}
count++;
}
if (size > 1)
{
close(oldpipe[0]);
close(oldpipe[1]);
}
printf("Finished Pipeline\n");
exit(3);
}
else
{
//*
int status = 0;
commands->pid = pid;
//Parent
if (!background)
{
pipeline->status = FOREGROUND;
if (waitpid(pid, &status, 0) < 0)
printf("waitpid ERROR\n");
list_remove(&pipeline->elem);
}
else
pipeline->status = BACKGROUND;
//*/
}
esh_signal_unblock(SIGCHLD);
I am fairly certain the error has to do with either the piping, or the forking of child processes in the loop.

Resources