所用代码如下:
#include <stdio.h> #include <sys/types.h> #include <unistd.h> int main() { //pid_t是数据类型,实际上是一个整型,通过typedef重新定义了一个名字,用于存储进程id pid_t pid; //scanf("%d",&i);//让进程等待,方便使用shell观察进程pid pid= getpid(); //getpid()函数返回当前进程的id号 printf("Process id :%d\n", pid); return 0; }使用如下命令打开gedit
gedit your_file_name将代码复制到打开的文本编辑器里,并保存。使用如下指令进行编译
gcc your_file_name -o output_name需要注意的是源代码必须以.c结尾,否则会报如下错误 运行,发现了进程的pid为: 将代码的scanf注释取消,重新运行,使用如下指令
ps -al可在进程列表中观察到对于的进程:
运行结果为 可以发现两个现象:
出现了两个Afterfock语句,原因在于使用了fock函数后,Linux创建了一个进程,该进程的EIP寄存器值被设为fock()函数后的语句在两个Afterfock语句之间出现了shell提示符,该原因为在子进程在主进程运行完成之后才被调度,此时shell进程已被调度,输出了shell提示符。将阻塞函数加入后,再次运行。 可以发现猜测是正确的。利用ps -al指令可以观察到PID(process id)和PPID(parent process id)
实验代码为:
#include <stdio.h> #include <sys/types.h> #include <unistd.h> int main() { pid_t cid; printf("Before fork process id :%d\n", getpid()); cid = fork(); if(cid == 0){ //该分支是子进程执行的代码 printf("Child process id (my parent pid is %d):%d\n", getppid(),getpid()); for(int i=0; i<3 ; i++) printf("hello\n"); }else{ //该分支是父进程执行的代码 printf("Parent process id :%d\n", getpid()); for(int i=0; i<3 ; i++) printf("world\n"); } return 0; }循环三次的运行结果为: 循环三百次的结果为: 可以看到…效果似乎不是很理想,三百次的循环也没有将一次进程调度的时间片耗尽,为此最好在循环中加一个阻塞函数sleep即可实现想要观察到的并发效果: 可以看到,在加了阻塞函数之后,进程主动放弃运行权,后再次被调度到,此时两个进程可以看出并发执行。
实验代码为:
#include <sys/types.h> #include <unistd.h> int main() { pid_t cid; int x = 100; cid = fork(); if (cid == 0) { //该分支是子进程执行的代码 x++; printf("In child: x=%d\n", x); } else { //该分支是父进程执行的代码 x--; printf("In parent: x=%d\n", x); } return 0; }编译运行,可以看到结果如下: 这验证了两个进程中的变量X是相互独立的。 添加了阻塞函数后的代码为:
#include <sys/types.h> #include <unistd.h> #include <sys/wait.h> #include<stdio.h> int main() { pid_t cid; int x = 100; cid = fork(); if (cid == 0) { //该分支是子进程执行的代码 x++; printf("In child: x=%d\n", x); sleep(3); } else { //该分支是父进程执行的代码 wait(NULL); x--; printf("In parent: x=%d\n", x); } return 0; }运行结果为: 可以看到,在加了阻塞函数之后,两个进程的调度被控制了,此时能够更加清晰的观察到两个变量是独立的。
实验代码为:
#include <sys/types.h> #include <unistd.h> #include <stdio.h> #include <pthread.h> void *threadFunc(void *arg) { //线程函数 printf("In NEW thread\n"); } int main() { pthread_t tid; pthread_create(&tid, NULL, threadFunc, NULL); //线程创建函数 pthread_join(tid, NULL); //等待指定的线程结束 printf("In main thread\n"); return 0; }其中pthread_create的函数声明为:
int pthread_create(pthread_t *tidp,const pthread_attr_t *attr,\ void *(*start_rtn)(void*),void *arg);可以看到,第三个参数定义了线程的开始地址,第四个参数向线程压入了一个参数。 而pthread_join的函数声明为:
int pthread_join(pthread_t thread, void **retval);其中第二个参数为线程返回的函数,这个函数的作用是等待指定的进程结束。那为什么要调用这个函数呢?这里有一篇博客解释了这个原因,也简要解释了Linux环境下线程的创建和工作过程。 https://blog.csdn.net/heybeaman/article/details/90896663 采用如下指令编译
gcc helloThread.c -o helloThread -pthread运行 可以发现,两个线程都被运行了起来。 将pthread_join进行注释,重新编译运行 可以看到,新创建的线程并没有得到运行的机会。 原因可以在上面的博客中找到答案:main主线程创建完新的线程之后就运行完了,此时整个进程已经运行完毕,资源被系统回收,新创建的线程再也没有机会得到运行。
实验代码如下:
#include <sys/types.h> #include <unistd.h> #include <stdio.h> #include <pthread.h> void* hello(void* arg){ //线程函数 for(int i=0;i<300;i++) printf("hello(%d)\n",i); } void* world(void* arg){ //线程函数 for(int i=0;i<300;i++) printf("world(%d)\n",i); } int main() { pthread_t tid1,tid2; pthread_create(&tid1, NULL, hello, NULL); pthread_create(&tid2, NULL, world, NULL); pthread_join(tid1, NULL); pthread_join(tid2, NULL); printf("In main thread\n"); return 0; }运行,可以发现效果并不好… 其原因和父子进程的原因差不多:时间片还没有耗尽时一个线程就已经结束了。我们修改一下实验代码
#include <unistd.h> #include <stdio.h> #include <pthread.h> void *hello(void *arg) { //线程函数 for (int i = 0; i < 3; i++){ sleep(0.1); printf("hello(%d)\n", i); } } void *world(void *arg) { //线程函数 for (int i = 0; i < 3; i++){ sleep(0.1); printf("world(%d)\n", i); } } int main() { pthread_t tid1, tid2; pthread_create(&tid1, NULL, hello, NULL); pthread_create(&tid2, NULL, world, NULL); pthread_join(tid1, NULL); pthread_join(tid2, NULL); printf("In main thread\n"); return 0; }重新编译运行: 可以观察到对应的线程的并发执行。
代码如下
#include <unistd.h> #include <stdio.h> #include <pthread.h> int global_value=100; void *hello(void *arg) { //线程函数 for (int i = 0; i < 3; i++){ sleep(0.1); printf("hello(%d)\n", global_value++); } } void *world(void *arg) { //线程函数 for (int i = 0; i < 300; i++){ sleep(0.1); printf("world(%d)\n", global_value++); } } int main() { pthread_t tid1, tid2; pthread_create(&tid1, NULL, hello, NULL); pthread_create(&tid2, NULL, world, NULL); pthread_join(tid1, NULL); pthread_join(tid2, NULL); printf("In main thread,the global_value(%d)\n",global_value); return 0; }编译运行:
可以看到,变量确实是共享的