1头文件
#include <sched.h>
#include<pthread.h>
2函数原型
int sched_setaffinity(pid_t pid, unsigned int cpusetsize, cpu_set_t *mask);
int sched_getaffinity(pid_t pid, unsigned int cpusetsize, cpu_set_t *mask);
void CPU_CLR(int cpu, cpu_set_t *set);
int CPU_ISSET(int cpu, cpu_set_t *set);
void CPU_SET(int cpu, cpu_set_t *set);
void CPU_ZERO(cpu_set_t *set);
3 clone函数
#include <sched.h>
int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...);
clone() 类似于fork()函数创建一个新的进程。
这里fn是函数指针,指向子进程的应用函数指针, child_stack为子进程分配堆栈空间(在linux下系统堆栈空间是2页面,就是8K的内存,其中在这块内存中,低地址上放入了值,这个值就是进程控制块task_struct的值), flags就是标志用来描述你需要从父进程继承那些资源, arg就是传给子进程的参数)
flags可取值:
标志 含义
CLONE_PARENT 创建的子进程的父进程是调用者的父进程,新进程与创建它的进程成了“兄弟”而不是“父子”
CLONE_FS 子进程与父进程共享相同的文件系统,包括root、当前目录、umask
CLONE_FILES 子进程与父进程共享相同的文件描述符(file descriptor)表
CLONE_NEWNS 在新的namespace启动子进程,namespace描述了进程的文件hierarchy
CLONE_SIGHAND 子进程与父进程共享相同的信号处理(signal handler)表
CLONE_PTRACE 若父进程被trace,子进程也被trace
CLONE_VFORK 父进程被挂起,直至子进程释放虚拟内存资源
CLONE_VM 子进程与父进程运行于相同的内存空间
CLONE_PID 子进程在创建时PID与父进程一致
CLONE_THREAD Linux 2.4中增加以支持POSIX线程标准,子进程与父进程共享相同的线程群
通过不同的flag参数的传递,是的子进程和父进程共享不同的空间。这样就看起来是的子线程看起来像一个子进程。
在应用中可以采用:
#define CLONE_BUDDY_FLGS (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD )
4 示例代码运行结果
[root@localhost codeset]# gcc -o psbind psbind.c -lpthread
[root@localhost codeset]# ./psbind
Process (5200) is created and bound to CPU (0)
Process (5201) is created and bound to CPU (1)
Process (5201) is created and bound to CPU (1)
allocate memory in cpu(1)
cpu (1) value before change is: 5201
cpu (1) value after change is: 1
cpu (0) value before change is: 1
cpu (0) value after change is: 0
5运行结果分析
首先,在void process_bind_x86()函数中采用clone函数创建了新的子进程,并依次绑定了物理线程上。
然后,各个子进程开始运行,执行函数int process_packet(void *args)。在该函数中,判断全局变量是否有开辟内存,如果没有则开内存,并赋初值为当前进程号,然后打印初值和改变值(改成当前物理线程号)。如果已经开辟,就直接打印全局变量的值,并将其修改成进程所在的物理线程号。物理线程号的获取通过获取亲属性判断。
总结:通过本实例,可以看到,通过clone创建的子进程绑定了实际的物理线程,并且在任何线程开辟的内存,其他线程都是可以读写的。