linux下多线程编程与调试

linux下多线程编程之pthread

pthread_self() 可获取当前线程号。

getpid() 可获取当前进程号。

pthread_join(t1, NULL); 等待子线程执行完。

pthread_exit("a string"); 在线程中使用,线程返回后,会将 “a string” 字符串给主进程 pthread_join(t1, &result) 中的result。

如下示例代码可以看出这以上各函数的作用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//gcc test.c lpthread -o test
//test.c
#include <stdio.h> //printf
#include <pthread.h> //pthread_xxx

void *thread_func(void *p)
{
long i = (long)p;
pthread_t tid = pthread_self();
for (int j = 0; j < 5; j++)
{
printf("thread id is:%lu --- %d --- %d\n",tid,i,j);
}

return NULL;
}

int main()
{
pthread_t t1, t2;
pid_t pid = getpid();
printf("PID is: %lu\n",pid);
pthread_create(&t1, 0, thread_func, (void *)1);
pthread_create(&t2, 0, thread_func, (void *)2);

// pthread_join(t1, NULL);
// pthread_join(t2, NULL);

return 0;
}

参考:

pthread常用函数

pthread并行编程入门

linux下多进程编程之fork

fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程。

  • 在父进程中,fork返回新创建子进程的进程ID;
  • 在子进程中,fork返回0;
  • 如果出现错误,fork返回一个负值;
    如下代码可以帮助我们了解fork()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>

int main ()
{
pid_t fpid;
int count=0;
fpid=fork();
if (fpid < 0)
printf("error in fork!\n");
else if (fpid == 0) {
printf("i am the child process, getpid() is: %d,getppid() is: %d,fpid is: %d\n",getpid(),getppid(),fpid);
count++;
}
else {
printf("i am the parent process, getpid() is: %d,getppid() is: %d,fpid is: %d\n",getpid(),getppid(),fpid);
count++;
count++;
}
printf("count is: %d\n",count);
return 0;
}

参考:

linux中fork()函数详解(原创!!实例讲解)

ptrace

  • ptrace追踪子进程系统调用号
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 64 bit system
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/reg.h>
#include <sys/user.h> /* For constants
ORIG_EAX etc */
int main()
{
pid_t child;
long orig_eax;
long test;
child = fork();
if(child == 0) {
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
execl("/bin/ls", "ls", NULL);
}
else {
wait(NULL);
orig_eax = ptrace(PTRACE_PEEKUSER,child, 8 * ORIG_RAX,NULL);
printf("The child made a system call %ld\n",orig_eax);
ptrace(PTRACE_CONT, child, NULL, NULL);
}
return 0;
}
  • ptrace进程附着调试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/reg.h>
#include <sys/user.h> /* For constants
ORIG_EAX etc */

int main(int argc, char *argv[])
{
pid_t traced_process;
struct user_regs_struct regs;
long ins;
if(argc != 2) {
printf("Usage: %s <pid to be traced> ",argv[0]);
exit(1);
}
traced_process = atoi(argv[1]);
ptrace(PTRACE_ATTACH, traced_process,
NULL, NULL);
wait(NULL);
ptrace(PTRACE_GETREGS, traced_process,
NULL, &regs);
printf("regs.rip is: 0x%llx\n",regs.rip);
ins = ptrace(PTRACE_PEEKTEXT, traced_process,
regs.rip, NULL);
printf("RIP: %llx Instruction executed: %lx\n",regs.rip, ins);
ptrace(PTRACE_DETACH, traced_process,
NULL, NULL);
return 0;
}

参考:

Linux沙箱之ptrace

ptrace运行原理及使用详解