I'm reading Operating Systems: Three Easy Pieces and I'm finding a problem is not mentioned in the book.
This is the C script:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
/*#include "common.h"*/
#include <unistd.h>
#include <assert.h>
int
main(int argc, char *argv[])
{
int *p = malloc(sizeof(int));
assert(p != NULL);
printf("(%d address pointed to by p: %p\n",
getpid(), p);
*p = 0;
while (1) {
sleep(1);
*p = *p +1;
printf("(%d) p: %d\n", getpid(), *p);
}
return 0;
}
It allocates some memory, prints out the address memory, puts the number 0 into it and finally loops to increment the value.
I compile it through gcc -o mem mem.c -Wall and I have no problem running it with ./mem, if I press CRTL+C it will stop:
But then problems come when I run the script twice in parallel with the command ./mem & ./mem, look at the GIF:
No matter how many times I try to kill the process the scripts keeps hammering.
How to kill my C which project?
Use fg to bring the backgrounded process to the foreground, then it will respond to Ctrl-C.
You can also use jobs to see a numbered list of backgrounded jobs, and kill %<number> to kill a specific job, e.g. kill %1.
Related
Can please some one explain the output of the code below!
I was working with threads in C language, and caught my eye that sometimes the output of the programs is not totally one of my prediction.
So I tried to write this code to understand more..
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
void * threadfun(void *arg){
printf("Hello from thread id %ld\n",*(pthread_t*)arg);
return NULL;
}
int main (int argc, char *argv[]){
pthread_t tid;
void * (*fp)(void*) = &threadfun;
printf("The Main program. pid = %d.\n",getpid());
pthread_create(&tid, NULL,fp,(void*)&tid);
printf("%ld was the thread id.\n",tid);
//pthread_join(tid, NULL);
printf("ENd. \n");
return 0;
}
I comment out the join function on purpose.
The output of this code was sometimes something like this:
gcc (Debian 11.2.0-10) 11.2.0
└─$ gcc s1_LD_thread01.c -o out_s1_thread01 -lpthread
└─$ ./out_s1_thread01
The Main program. pid = 8683.
140305239197248 was the thread id.
ENd.
Hello from thread id 140305239197248
Hello from thread id 140305239197248
I am wondering why the created thread outputting two strings.!
I am developing a Hobby operating system, for that I want to know the mechanism of memory allocation in Linux, to understand that, I created a simple C program that defines a unsigned char of some hex numbers and then runs in a empty infinite loop, I did this to keep the process alive. Then I used pmap to get page-mapping information. Now I know the location of stack segment, also I have created a program that uses process_vm_readv syscall to read the contents of that address, all I see a stream of 00 when I read the contents of stack segment and some random numbers at last, How can I be able to figure out how the array is stored in the stack segment?
If that is possible, how can I analyze the hex stream to extract meaningful information ?
Here I am adding a demonstration for accessing address space of a remote process, There are two programs local.c which will read and write a variable in another program named remote.c (These program assumes sizeof(int)==4 )
local.c
#define _GNU_SOURCE
#include <sys/uio.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/syscall.h>
int main()
{
char buf[4];
struct iovec local[1];
struct iovec remote[1];
int pid;
void *addr;
printf("Enter remote pid\n");
scanf("%d",&pid);
printf("Enter remote address\n");
scanf("%p", &addr);
local[0].iov_base = buf;
local[0].iov_len = 4;
remote[0].iov_base = addr;
remote[0].iov_len = 4;
if(syscall(SYS_process_vm_readv,pid,local,1,remote,1,0) == -1) {
perror("");
return -1;
}
printf("read : %d\n",*(int*)buf);
*(int*)buf = 4321;
if(syscall(SYS_process_vm_writev,pid,local,1,remote,1,0) == -1) {
perror("");
return -1;
}
return 0;
}
remote.c
#define _GNU_SOURCE
#include <sys/uio.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/syscall.h>
int main()
{
int a = 1234;
printf("%d %p\n",getpid(),&a);
while(a == 1234);
printf ("'a' changed to %d\n",a);
return 0;
}
And if you run this on a Linux machine,
[ajith#localhost Desktop]$ gcc remote.c -o remote -Wall
[ajith#localhost Desktop]$ ./remote
4574 0x7fffc4f4eb6c
'a' changed to 4321
[ajith#localhost Desktop]$
[ajith#localhost Desktop]$ gcc local.c -o local -Wall
[ajith#localhost Desktop]$ ./local
Enter remote pid
4574
Enter remote address
0x7fffc4f4eb6c
read : 1234
[ajith#localhost Desktop]$
Using the similar way you can read stack frame to the io-vectors, But you need to know the stack frame structure format to parse the values of local variables from stack frame. stack frame contains function parameters, return address, local variables, etc
I am looking for a ptrace() call to observe a process until the process exits.
I have this which compiles with gcc / cc on OSX:
#include <sys/types.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <stdio.h>
#include <sys/ptrace.h>
int main(int argc, char *argv[]) {
pid_t pidx = atoi(argv[1]);
printf("pid = %jd\n", (intmax_t) pidx);
ptrace(PT_ATTACHEXC, pidx, 0, 0);
wait(NULL);
}
However, even with a valid/existing pid, this program will still exit immediately. I am trying to only exit this program after pidx dies.
Is this possible somehow?
Ideally I want something that works on both OSX and Linux.
Your problem is probably that the wait call returns immediately, because the traced "inferior" process is suspended, you know, waiting for you to debug it. You're going to need some kind of loop in which you make ptrace requests to inspect the child and then resume execution, and then call wait again to wait for it to suspend on the next breakpoint or whatever. Unfortunately the debugger API is extremely non-portable; you will have to write most of this program twice, once for OSX and once for Linux.
Is it possible to generate a mini core dump for debugging purpose without crashing the process. Let's say if a function receives an unexpected value, just printing logs and returning gracefully might not be sufficient to debug the issue. On the other hand, if i can get a screenshot of memory and look at the stack, i could find more useful information to debug.
Yes,
According to gdb's documentation, once attached with gdb you may issue the following command:
(gdb) gcore
(gdb) q
This will dump the core to "core.pid" without crashing the process.
or this one-liner:
sudo sh -c 'echo gcore <output_core> | gdb -p <pid>'
There is not building function to do that, you could use ptrace() to debug your own process but it would not be easy. Call gcore is the easiest method.
#include <stdio.h>
#include <unistd.h>
#include <inttypes.h>
#include <sys/wait.h>
int main(void) {
pid_t parent = getpid();
pid_t pid = fork();
if (pid < 0) {
// oh dear we are on trouble
} else if (pid == 0) {
char tmp[42];
snprintf(tmp, sizeof tmp, "%" PRIdMAX, (intmax_t)parent);
execvp("gcore", (char *[]){"gcore", tmp, NULL});
} else {
int wstatus;
waitpid(pid, &wstatus, 0);
}
}
This question already has answers here:
C - Executing Bash Commands with Execvp
(3 answers)
Closed 6 years ago.
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
void main(){
char *cmd;
pid_t pid;
while (1) {
printf("$ ");
fgets(cmd,1000,stdin);
if (pid = fork() == -1) {
exit(1);
}
else if (pid == 0){
execvp(cmd,&cmd);
}
else{
int status;
wait(&status);
}
}
}
I am making a simple shell that executes commands but when I enter the command at the prompt I keep getting segmentation fault. This is the most simple version that only works for one-argument commands like "ls"
For your problem, in your code,
fgets(cmd,1000,stdin);
cmd is uninitialized. It does not point to a valid memory. Accessing invalid memory invokes undefined behavior.
You need to allocate memory to cmd before you ca use that. Alternatively, you can consider making cmd an array, like char cmd[1000] = {0}; to avoid the need to allocate memory yourself.
Then, execvp(cmd,&cmd); is not quite right, it's not what you think it is. Read the man page for a better understanding.
That said, for a hosted environment, void main() should at least be int main(void) to have standard conformance.