Linux - Syscall to Iterate over children threads - linux

I am creating a syscall to return some information about a process and its children threads. I am testing this in Ubuntu 14.04. Here is the code that I have written:
#include <linux/list.h>
#include <linux/linkage.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
#define NUM_THREADS 5
struct thread_info_prj {
int pid;
int nthreads;
int tid[NUM_THREADS];
};
asmlinkage void sys_threadinfo_prj(void *ptr)
{
struct task_struct *task;
struct thread_info_prj t_info;
struct list_head *list;
int num_threads = 0;
t_info.pid = current->pid;
list_for_each(list, &current->children) {
//task = list_entry(&p_task->children, struct task_struct, sibling);
task = list_entry(list, struct task_struct, sibling);
t_info.tid[num_threads] = task->pid;
num_threads++;
}
t_info.nthreads = num_threads;
copy_to_user(ptr, &t_info, sizeof(struct thread_info_prj));
}
This code is built into the kernel as a syscall , and tested with the following program.
#include <pthread.h>
#include <stdio.h>
#include <sys/syscall.h>
#include <errno.h>
#define NUM_THREADS 5
struct thread_info_prj {
int pid;
int nthreads;
int tid[NUM_THREADS];
};
void * thread_fn(void *ptr) {
printf("Im a thread!\n");
sleep(4);
pthread_exit(NULL);
}
int main() {
pthread_t threads[NUM_THREADS];
pthread_attr_t attr;
int i;
struct thread_info_prj t_info;
void *status;
pthread_attr_init(&attr);
//pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for (i = 0; i < NUM_THREADS; i++)
pthread_create(&(threads[i]), &attr, thread_fn, NULL);
sleep(1);
syscall(352, &t_info);
//for (i = 0; i < NUM_THREADS; i++)
// pthread_join(threads[i], &status);
printf("PID: %d\n", t_info.pid);
printf("Num Threads: %d\n", t_info.nthreads);
for (i = 0; i < t_info.nthreads; i++) {
printf("Thread ID: %d\n", t_info.tid[i]);
}
printf("%s\n",strerror(errno));
return 0;
}
Unfortunately, the only output is the proper parent pid. Otherwise, it returns that there are no threads and does not print any additional PIDs. By adding a printk inside the for loop, I discovered that it never even enters the for loop. Any suggestions?
Thanks so much.

Related

Alternate Without Semaphores

The program below creates two processes.
The parent process prints the numbers from 0 to 9, while the
child process prints the characters from A to J.
How can I make it alternate the printing using only signals? so no using semaphores or any IPCs.
#include <stdio.h>
int main()
{
int i = 0;
if (fork() == 0) /* Child process */
{
for (i = 0; i < 10; i++) {
printf("%c\n", i + 65);
}
} else /* Parent process */
{
for (i = 0; i < 10; i++) {
printf("%d\n", i);
}
}
}
I figured it out.
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#include <signal.h>
int main()
{
int i=0;
int status;
int childPID = fork();
if (childPID == 0) /* Child process */
{
for(i=0;i<10;i++){
printf("%c\n",i+65);
kill(getpid(), SIGSTOP);
}
} else /* Parent process */
{
for(i=0;i<10;i++) {
waitpid(childPID,&status,WUNTRACED);
printf("%d\n",i);
kill(childPID, SIGCONT);
}
}
}

write_proc is not invoked when written from userspace

I am trying to understand procfs for communication between userspace and kernel module. My module has basic two functions for procfs write_proc, driver_mmap.
I call multiple times write_proc by calling fputs("123456789",fd). where fd is file descriptor to procfs entry in /proc directory. But I don't see write_proc called multiple time. Code is attached by here.
<code>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/mm.h> /* mmap related stuff */
#define BUF_SIZE 64 * 1024
int *MmapBuffer;
int Factor = 1;
static int write_proc(struct file *filp, int *buf, size_t count, loff_t *offp)
{
int rc,i;
printk("in Write \n");
for (i = 1; i <= 16*1024 ; i++)
MmapBuffer[i-1] = (i+1)*Factor;
Factor++;
return count;
}
static int driver_mmap(struct file *file, struct vm_area_struct *vma)
{
int ret;
vma->vm_flags |= VM_LOCKED|VM_SHARED;
ret = remap_pfn_range(vma, vma->vm_start,
virt_to_phys(MmapBuffer) >> PAGE_SHIFT,
vma->vm_end-vma->vm_start, vma->vm_page_prot);
if(ret != 0)
printk("MMAP Failed \n");
SetPageReserved(virt_to_page(MmapBuffer));
printk("MMAP Succeeded \n");
return 0;
}
// file operations
struct file_operations proc_fops =
{
.write = write_proc,
.mmap = driver_mmap,
};
// init module
int init_module_test(void)
{
printk("<1>Hello world\n");
MmapBuffer = kzalloc(BUF_SIZE,__GFP_COLD|GFP_DMA);
if(MmapBuffer == NULL)
printk("Kzalloc failed. reduce buffer size \n");
proc_create ("Test_fs",0,NULL, &proc_fops);
return 0;
}
// exit module
void cleanup_module_test(void)
{
kfree(MmapBuffer);
remove_proc_entry ("Test_fs", NULL);
printk("Goodbye world\n");
}
module_init(init_module_test);
module_exit(cleanup_module_test);
MODULE_LICENSE("GPL");
</code>
Application code
<code>
#include<stdio.h>
#include<stdlib.h>
#include<sys/mman.h>
#include<errno.h>
#include <fcntl.h>
int main(void)
{
int fd;
int i,j;
int *msg ;
printf("Allocation started \n ");
msg=(int*)malloc(64*1024);
if(msg == NULL)
printf("Allocation failed \n");
//unsigned int *addr;
printf("Starting opening \n ");
if((fd=open("/proc/Test_fs", O_RDONLY ))<0)
{
printf("File not opened ");
}
printf("Starting mapping \n ");
msg = mmap(NULL, 64*1024, PROT_READ, MAP_SHARED , fd, 0);
printf("done from module \n ");
if(msg == MAP_FAILED)
{
printf("MAP failed and error is %s", strerror(errno));
return 0;
}
close(fd);
printf("Successful mapping");
FILE *f;
f=fopen("/proc/Test_fs", "wr");
if(!f)
{
printf("File not opened ");
}
for (j = 0; j < 10 ; j++)
{
if(fputs("1234567890,",f) <= 0)
printf("write failed, ");
for (i = 0; i < 16*1024 ; i++)
printf("%d, ", msg[i]);
printf("\n \n done \n \n ");
}
fclose(f);
return 0;
}
</code>

trying to use pipe(2) with the sort unix tool but not working

I have been struggling to find what I'm doing wrong and I can't seem to find the issue. When I compile the code below, I get an I/O error.
e.g: /usr/bin/sort: read failed: -: Input/output error
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char **argv, char **envp)
{
int fd[2];
pid_t pid;
pipe(fd);
pid = fork();
if (pid == -1) {
exit(EXIT_FAILURE);
}
if (pid == 0) { /* child */
char *exe[]= { "/usr/bin/sort", NULL };
close(fd[0]);
execve("/usr/bin/sort", exe, envp);
}
else {
char *a[] = { "zilda", "andrew", "bartholomeu", NULL };
int i;
close(fd[1]);
for (i = 0; a[i]; i++)
printf("%s\n", a[i]);
}
return 0;
}
dup2(fd[0], 0) in the child.
dup2(fd[1], 1) in the parent.
close the other fd.

Pthread program returning expected declaration specifiers or â...â before â&â token

I am getting the same error multiple times when compiling the following pthreads program in linux using:
gcc -c -lpthread proj2_part1.c -lrt
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <semaphore.h>
#define BUFFER_SIZE 10
#define TRUE 1
struct cQueue{
int *buffer;
int front, rear;
}*queue;
int count;
pthread_mutex_t mutex;
sem_t full, empty;
........
/*MAIN*/
int main(int argc,char* argv[])
{
int a=0, b=0, count =0, buff[BUFFER_SIZE];
int p = atoi(argv[1]), c = atoi(argv[2]);
unsigned int s = atoi(argv[0]);
pthread_t prothread[p], conthread[c];
/*Initialize Semaphores*/
if (sem_init(&full,0,0) == -1)
printf("%s\n",strerror(errno));
if (sem_init(&empty,0,BUFFER_SIZE) == -1)
printf("%s\n",strerror(errno));
pthread_mutex_init(&mutex, NULL);
/*Initialize Circular Queue*/
queue->buffer=buff;
queue->front = queue->buffer[0];
queue->rear = queue->buffer[0];
if(argc!=3)
{
fprintf(stderr,"Syntax: ./a.out <int> <int> <int>");
return -1;
}
if(s<0)
{
fprintf(stderr,"Argument %d must be positive value\n",s);
return -1;
}
else
{
/*Create producer threads*/
int i;
for (i=0; i<p; i++)
{
b = pthread_create(&prothread[i], NULL, producerThread, (void*)argv[1]);
if (b<0)
{
printf("Error: unable to create thread, %d\n",b);
return -1;
}
}
/*Create consumer threads*/
int j;
for (j=0; j<c; j++)
(
a = pthread_create(&conthread[j], NULL, consumerThread, (void*)argv[2]);
if (a<0)
{
printf("Error: unable to create thread, %d\n",a);
return -1;
}
}
sleep(atoi(argv[0]));
}
return 0;
}
I am receiving the following error. I think it has something to do with my semaphore declaration.
proj2_part1.c:147:81: error: expected â)â before â;â token
a = pthread_create(&conthread[j], NULL, consumerThread, (void*)argv[2]);
^
proj2_part1.c:153:6: error: expected â;â before â}â token}
^
proj2_part1.c: At top level:
proj2_part1.c:156:6: error: expected identifier or â(â before âreturnâ
return 0;
^
proj2_part1.c:157:1: error: expected identifier or â(â before â}â token
}
You've used a ( where you meant {:
for (j=0; j<c; j++)
(

I read the counter's value with perf on linux,the value of it is always be 0

I run the program on Ubuntu 12.04,
The counters' value is awalys 0.It seems that my counters didn't work for me.
When I run the program,the ouput is :
Get the number of CPU:8
Create counters for each CPU finished!
run_perf_stat()!
Cache miss in cpu1:0
Cache miss in cpu2:0
Cache miss in cpu3:0
Cache miss in cpu4:0
Cache miss in cpu5:0
Cache miss in cpu6:0
Cache miss in cpu7:0
Cache miss in cpu8:0
I can't make sense of the values'meaning.What I want to get is every cpu's cache reference and it's cache miss.But obviously the result seems not correct!
I have read the doc about the perf method at:
http://www.man7.org/linux/man-pages/man2/perf_event_open.2.html
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <asm-generic/unistd.h>
#include <dirent.h>
#include <sys/ioctl.h>
#include <linux/perf_event.h>
#include <asm/unistd.h>
#include "perf_event.h"
#define MAX_COUNTERS 256
static int fd[MAX_COUNTERS];
static unsigned int counter;
static unsigned int nr_cpus = 0; // amount of cpus
//open counter
long sys_perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
int cpu, int group_fd, unsigned long flags)
{
int ret;
ret = syscall(__NR_perf_event_open, hw_event, pid, cpu,
group_fd, flags);
return ret;
}
void run_perf_stat()
{
long long eventContents=0;
for (counter = 0; counter < nr_cpus; counter++){
if(fd[counter]!=-1){
read(fd[counter],&eventContents,sizeof(long long));
printf("Cache miss in cpu%d:%lld\n",counter+1,eventContents);
}
else{
fprintf(stderr, "Fail to read counter %d\n", counter);
}
}
}
int main(int argc, const char **argv){
DIR *dir; //access to dir
struct dirent *drp;
int run_count, p, pid;
struct timespec tim, tim2;
tim.tv_sec = 1; tim.tv_nsec = 0;
nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);// the number of CPU
printf("Get the number of CPU:%d\n",nr_cpus);
//create counters for each CPU (system-wide)
struct perf_event_attr attr; //cache miss
memset(&attr, 0, sizeof(struct perf_event_attr));
attr.type = PERF_TYPE_HARDWARE;
attr.config = PERF_COUNT_HW_CACHE_MISSES;
attr.size = sizeof(struct perf_event_attr);
attr.disabled = 0;
attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
PERF_FORMAT_TOTAL_TIME_RUNNING;
unsigned int cpu = 0;
for(cpu = 0; cpu < nr_cpus; cpu++)
fd[cpu] = sys_perf_event_open(&attr, -1, cpu, -1, 0);
printf("Create counters for each CPU finished!\n");
//get perf report
while (1) {
nanosleep(&tim , &tim2);
printf("run_perf_stat()!\n");
run_perf_stat();
}
return 1;
}
And I also run the example given at http://www.man7.org/linux/man-pages/man2/perf_event_open.2.html
But,unfortunaely,The result is always 0,too.Here comes the example in the man-page.
The following is a short example that measures the total instruction count of a call to printf(3).
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/perf_event.h>
#include <asm/unistd.h>
long
perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
int cpu, int group_fd, unsigned long flags)
{
int ret;
ret = syscall(__NR_perf_event_open, hw_event, pid, cpu,
group_fd, flags);
return ret;
}
int
main(int argc, char **argv)
{
struct perf_event_attr pe;
long long count;
int fd;
memset(&pe, 0, sizeof(struct perf_event_attr));
pe.type = PERF_TYPE_HARDWARE;
pe.size = sizeof(struct perf_event_attr);
pe.config = PERF_COUNT_HW_INSTRUCTIONS;
pe.disabled = 1;
pe.exclude_kernel = 1;
pe.exclude_hv = 1;
fd = perf_event_open(&pe, 0, -1, -1, 0);
if (fd == -1) {
fprintf(stderr, "Error opening leader %llx\n", pe.config);
exit(EXIT_FAILURE);
}
ioctl(fd, PERF_EVENT_IOC_RESET, 0);
ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);
printf("Measuring instruction count for this printf\n");
ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
read(fd, &count, sizeof(long long));
printf("Used %lld instructions\n", count);
close(fd);
}
I just tried your code and removing following lines (line no 75,76) makes the code work for me.
attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
PERF_FORMAT_TOTAL_TIME_RUNNING;

Resources