java如何根据pid转tid_C语言编程中pid, tid以及真实pid的关系(转)

add by zhj: 下面是我对pid,tgid,ppid的个人理解

对于ubuntu14.04操作系统,可以在/usr/src/linux-headers-4.4.0-31/include/linux/sched.h文件中看到进程控制块的结构体,如下

structtask_struct {volatile long state; /*-1 unrunnable, 0 runnable, >0 stopped*/

void *stack;

atomic_t usage;

unsignedint flags; /*per process flags, defined below*/unsignedintptrace;

#ifdef CONFIG_SMPstructllist_node wake_entry;inton_cpu;

unsignedintwakee_flips;

unsignedlongwakee_flip_decay_ts;struct task_struct *last_wakee;intwake_cpu;#endif......

......

pid_t pid;

pid_t tgid;

......

......

}

可以看到,里面定义了两个字段,pid和tgid,其中pid就是这个轻量级进程lwp的id,而tgid是轻量级进程组的id,当创建进程时,我们可以为自己指定

进程的tgid字段,貌似可以随便指定,只要存在就行,另外在父进程中,可以为子进程设置进程组id,如果没有指定,它会继承父进程的进程组id。

还有一个概念ppid,我没在这个结构体中找到,但操作系统肯定是会记录的,在Python中,通过os.get_ppid()就可以获取当前进程的父进程。tgid与ppid,

这两者其实没有任何关系,因为tgid是可以自己来指定的,平时基本不用,不用管它。

1、pid,tid,真实pid的使用

进程pid: getpid() // 相当于os.getpid()

线程tid: pthread_self()//进程内唯一,但是在不同进程则不唯一。相当于thread.get_ident()

线程pid: syscall(SYS_gettid) //系统内是唯一的。python中没有现成的方法,需要手动调用动态链接库ctypes.CDLL('libc.so.6').syscall(xx)

#include#include#include#include

structmessage

{inti;intj;

};void *hello(struct message *str)

{

printf("child, the tid=%lu, pid=%d",pthread_self(),syscall(SYS_gettid));

printf("the arg.i is %d, arg.j is %d",str->i,str->j);

printf("child, getpid()=%d",getpid());while(1);

}int main(int argc, char *argv[])

{structmessage test;

pthread_t thread_id;

test.i=10;

test.j=20;

pthread_create(&thread_id,NULL,hello,&test);

printf("parent, the tid=%lu, pid=%d",pthread_self(),syscall(SYS_gettid));

printf("parent, getpid()=%d",getpid());

pthread_join(thread_id,NULL);return 0;

}

ae70968bc07eeeae19728c817f6aae09.png

getpid()得到的是进程的pid,在内核中,每个线程都有自己的PID,要得到线程的PID,必须用syscall(SYS_gettid);

pthread_self函数获取的是线程ID,线程ID在某进程中是唯一的,在不同的进程中创建的线程可能出现ID值相同的情况。

#include #include#include#include#include

void *thread_one()

{

printf("thread_one:int %d main process, the tid=%lu,pid=%ld",getpid(),pthread_self(),syscall(SYS_gettid));

}void *thread_two()

{

printf("thread two:int %d main process, the tid=%lu,pid=%ld",getpid(),pthread_self(),syscall(SYS_gettid));

}int main(int argc, char *argv[])

{

pid_t pid;

pthread_t tid_one,tid_two;if((pid=fork())==-1)

{

perror("fork");

exit(EXIT_FAILURE);

}else if(pid==0)

{

pthread_create(&tid_one,NULL,(void *)thread_one,NULL);

pthread_join(tid_one,NULL);

}else{

pthread_create(&tid_two,NULL,(void *)thread_two,NULL);

pthread_join(tid_two,NULL);

}

wait(NULL);return 0;

}

1153ee29b0ad02cf149ec45de9146dee.png

2、pid与tid的用途

Linux中,每个进程有一个pid,类型pid_t,由getpid()取得。Linux下的POSIX线程也有一个id,类型pthread_t,由pthread_self()取得,该id由线程维护,其id空间是各个进程独立的(即不同进程中的线程可能有相同的id)。你可能知道,Linux中的POSIX线程库实现的线程其实也是一个进程(LWP),只是该进程与主进程(启动线程的进程)共享一些资源而已,比如代码段,数据段等。

有时候我们可能需要知道线程的真实pid。比如进程P1要向另外一个进程P2中的某个线程发送信号时,既不能使用P2的pid,更不能使用线程的pthread id,而只能使用该线程的真实pid,称为tid。

有一个函数gettid()可以得到tid,但glibc并没有实现该函数,只能通过Linux的系统调用syscall来获取。使用syscall得到tid只需一行代码,但为了加深各位看官的印象,简单提供下面场景。

有一簇进程,其中一个进程中另外启了一个线程。各进程共享一个数据结构,由shared_ptr指明,其中保存有线程的tid。在各个进程的执行过程中,需要判断线程是否存在,若不存在则(重新)创建。

首先,在线程函数的开始,需要将自己的tid保存至共享内存,

点击(此处)折叠或打开

#include 

#include 

void*

thread_func(void *args)

{

//~ lock shared memory

shared_ptr->tid = syscall(SYS_gettid); //~ gettid()

//~ unlock shared memory

//~ other stuff

}

在各进程中判断进程是否存在,

点击(此处)折叠或打开

//~ lock shared memory

pthread_t id;

if (shared_ptr->tid == 0) { //~ tid is initialized to 0

pthread_create(&id, NULL, thread_func, NULL);

} else if (shared_ptr->tid > 0) {

int ret = kill(shared_ptr->tid, 0); //~ send signal 0 to thread

if (ret != 0) { //~ thread already died

pthread_create(&id, NULL, thread_func, NULL);

}

}

//~ unlock shared memory

3、linux 系统中查看pid,tid的方法

线程进程都会有自己的ID,从操作系统来讲,这个ID就叫做PID

9457a2eb5cea110daf1140f6688abc21.png

b294a335b32ad47a50d322feae06f61d.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在S-Function,可以使用C语言来实现PID控制器。以下是一个简单的实现示例: ```c #define N 3 // 控制器状态变量数目 static void mdlInitializeSizes(SimStruct *S) { // 定义输入端口和输出端口 ssSetNumInputPorts(S, 2); ssSetInputPortWidth(S, 0, 1); // 输入量为误差e ssSetInputPortWidth(S, 1, 1); // 输入量为当前时刻的状态变量值x ssSetNumOutputPorts(S, 1); ssSetOutputPortWidth(S, 0, 1); // 输出量为控制量u // 定义状态变量 ssSetNumContStates(S, N); ssSetNumDiscStates(S, 0); // 定义控制器参数 ssSetNumSFcnParams(S, 3); // 三个参数:Kp、Ki、Kd ssSetSFcnParamTunable(S, 0, false); // Kp不可调节 ssSetSFcnParamTunable(S, 1, false); // Ki不可调节 ssSetSFcnParamTunable(S, 2, false); // Kd不可调节 // 定义可视化参数 ssSetOptions(S, SS_OPTION_WORKS_WITH_CODE_REUSE | SS_OPTION_USE_TLC_WITH_ACCELERATOR); } static void mdlInitializeSampleTimes(SimStruct *S) { // 定义采样时间 ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME); ssSetOffsetTime(S, 0, 0.0); } static void mdlStart(SimStruct *S) { // 初始化状态变量 real_T *x = ssGetContStates(S); x[0] = x[1] = x[2] = 0.0; } static void mdlOutputs(SimStruct *S, int_T tid) { // 获取输入量和参数 InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S, 0); InputRealPtrsType xPtrs = ssGetInputPortRealSignalPtrs(S, 1); real_T Kp = *mxGetPr(ssGetSFcnParam(S, 0)); real_T Ki = *mxGetPr(ssGetSFcnParam(S, 1)); real_T Kd = *mxGetPr(ssGetSFcnParam(S, 2)); // 获取输出量 real_T *y = ssGetOutputPortRealSignal(S, 0); // 计算控制器输出 real_T *x = ssGetContStates(S); real_T e = *uPtrs[0]; real_T x_current = *xPtrs[0]; real_T u = Kp * e + Ki * x[0] + Kd * (x_current - x[1]); y[0] = u; // 更新状态变量 x[0] += e; x[1] = x_current; x[2] = e; } static void mdlTerminate(SimStruct *S) { // 释放资源 } // 注册S-Function #ifdef MATLAB_MEX_FILE #include "simulink.c" #else #include "cg_sfun.h" #endif ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值