文章目录
如果父进程一直存在,子进程先退出了,父进程对子进程退出不管不顾,会出现什么样问题么?
创建makefile并输入以下内容
mytest:test.c
2 gcc -o $@ $^
3 .PHONY:clean
4 clean:
5 rm -f mytest
mytest 属于 目标文件
test.c 属于 依赖文件列表
$@代表目标文件
$^ 代表依赖文件列表
创建test.c并输入以下内容
#include<stdio.h>
2 #include<unistd.h>
3 int main()
4 {
5 pid_t id=fork();
6 if(id==0)
7 {
8 //子进程
9 while(1)
10 {
11 printf("我是子进程,我的pid是:%d,我的ppid是%d",getpid(),getppid());
12 sleep(1);
13 }
14
15 }
16 else if(id>0)
17 {
18 //父进程
19 int count=0;//父进程只运行10次
20 while(1)
21 {
22 printf("我是父进程,我的pid是:%d,我的ppid是%d",getpid(),getppid());
23 sleep(1);
24 if(count--<=0)
25 {
26 break;
27 }
28 }
29 }
30 }
复制SSH渠道,创建终端2,在保证终端1mytest运行的情况下,在终端2中输入指令
while :; do ps axj | head -1 && ps axj | grep mytest | grep -v grep ; sleep 1; echo "---------"; done
---------
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
17835 27831 27831 17835 pts/0 27831 S+ 1002 0:00 ./mytest
27831 27832 27831 17835 pts/0 27831 S+ 1002 0:00 ./mytest
当父子进程刚开始共存时,两者状态都是S+
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
1 27832 27831 17835 pts/0 17835 S 1002 0:00 ./mytest
当父进程运行结束后,子进程状态为S
正常来说,若父子进程中子进程结束,父进程要接收子进程的退出码结果,所以子进程处于僵尸状态
但是 父子进程中父进程结束,为什么父进程没有进入僵尸状态呢?
在操作系统当中由系统在开机之后帮我们维护的一些系统运行时的动态参数
我们自己写的代码,编译之后,运行的时候,为什么要带 ./ ?
那为什么运行系统的指令不需要 ./ ?
echo 作为打印字符串的一条命令
[yzq@VM-8-8-centos ~]$ echo abcd
abcd
echo $PATH 查看环境变量PATH
[yzq@VM-8-8-centos ~]$ echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/mydir/.local/bin:/home/mydir/bin
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/mydir/.local/bin:/home/mydir/bin
是以冒号作为分隔符,可以分割出来若干子路径
使用which 指令,搜索特定指令所对应的路径
[yzq@VM-8-8-centos my]$ which ls
alias ls='ls --color=auto'
/usr/bin/ls
ls的路径为 /usr/bin/ls
环境变量是从左到右,一条一条去查找,只要找到就停下来
ls指令在环境变量的usr/bin 路径下,说明 ls 指令不用带路径
修改自己写的可执行程序的路径,让其不用添加路径即可运行
创建test.c文件
#include<stdio.h>
2 int main()
3 {
4 printf("hello");
5 }
输入 gcc -o testc test.c ,生成testc可执行程序
输入 which testc ,查询testc的路径
[yzq@VM-8-8-centos my]$ which testc
/usr/bin/which: no testc in (/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/mydir/.local/bin:/home/mydir/bin)
说明 testc路径不在环境变量中
使用pwd ,查询当前testc的路径,
输入 export PATH=$PATH: 当前路径 ,将testc的路径新增到到环境变量中
[yzq@VM-8-8-centos my]$ pwd
/home/mydir/my
[yzq@VM-8-8-centos my]$ export PATH=$PATH:/home/mydir/my
[yzq@VM-8-8-centos my]$ testc
hello
直接 使用 testc ,就运行可执行程序
使用 env ,会出现如下环境变量

这些环境变量都是用户登录的时候设置好的,都是kv的
输入 echo $HOSTNAME 显示当前机器 名字
[yzq@VM-8-8-centos ~]$ echo $HOSTNAME
VM-8-8-centos
输入 echo $SHELL 显示当前所使用的shell
[yzq@VM-8-8-centos ~]$ echo $SHELL
/bin/bash
输入 echo $HOME,当前为普通用户
[yzq@VM-8-8-centos ~]$ echo $HOME
/home/mydir
HOME环境变量表示当前用户所对应的家目录
切换成root用户后, 此时对应root目录
[root@VM-8-8-centos mydir]# echo $HOME
/root
对于不同登录的人,同一个环境变量里面放的不同的内容,所以环境变量是针对特定的人在特定的场景使用的
main函数可以带3个参数分别为 int argc 和 char*argv [ ] 和char * envp[ ] (环境变量表)
创建test.c文件
#include<stdio.h>
2 #include<unistd.h>
3 int main(int argc,char*argv[],char*envp[])
4 {
5 int i=0;
6 for(i=0;envp[i];i++)
7 {
8 printf("envp[%d]->%s\n",i,envp[i]);
9 }
10 }
创建makefile
mytest:test.c
2 gcc -o mytest test.c
3 .PHONY:clean
4 clean:
5 rm -f mytest
输入 make ,使用./mytest 执行可执行程序
发现envp是一张传递给当前进程的环境变量表
char类型指针指向环境变量字符串
若main函数不传参数,还想要拿到环境变量,可以使用 environ
修改test.c文件
#include<stdio.h>
2 #include<unistd.h>
3 int main()
4 {
5 extern char** environ;//声明
6 int i=0;
7 for(i=0;environ[i];i++)
8 {
9 printf("environ[%d]->%s\n",i,environ[i]);
10 }
11 }
使用make, ./mytest执行可执行程序后
使用environ 也可以拿到所有环境变量
char* getenv(const char* name);
修改test.c文件
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<unistd.h>
4 int main()
5 {
6 char*user=getenv("USER");
7 if(user==NULL)
8 {
9 perror("getenv");
10 }
11 else
12 {
13 printf("USER:%s\n",user);
14 }
15 }
输入 make, ./mytest 执行可执行程序
[yzq@VM-8-8-centos my]$ ./mytest
USER:yzq
获取到user的名称
环境变量对应的数据,是从系统的相关配置文件中读取进来的
使用 cd ~ ,进入当前目录的主目录中
使用 ls -la , 显示隐藏文件

这是两个shell脚本,内部包含了配置文件
main函数的两个参数,char* argv[] 为指针数组 ,argv为一张表,包含一个个指针,指针指向字符串
int argc,argc为数组的元素个数
修改test.c文件
#include<stdio.h>
2 #include<stdlib.h>
#inlcude<string.h>
3 #include<unistd.h>
4 int main (int argc,char*argv[])
5 {
int i=0;
6 for(i=0;i<argc;i++)
7 {
8 printf("argv[%d]->%s\n",i,argv[i]);
10 }
使用make , ./mytest 执行可执行程序
[yzq@VM-8-8-centos my]$ ./mytest
argv[0]->./mytest
[yzq@VM-8-8-centos my]$ ./mytest -a
argv[0]->./mytest
argv[1]->-a
[yzq@VM-8-8-centos my]$ ./mytest -a -b
argv[0]->./mytest
argv[1]->-a
argv[2]->-b
./mytest -a -b,就是一个字符串
以空格作为分隔符,形成一个一个的子串
第一个./mytest为可执行程序,剩余的统称为参数选项
修改test.c文件
#include<stdio.h>
2 #include<stdlib.h>
3 #include<unistd.h>
4 #include<string.h>
5 void usage(const char*name)
6 {
7 printf("\nusage:%s-[a|b|c]\n\n",name);
8 exit(0);//终止进程
9 }
10 int main (int argc,char*argv[])
11 {
12 if(argc!=2)
13 {
14 usage(argv[0]);//argv[0]代表可执行程序
} }
15 if(strcmp(argv[1],"-a")==0)
16 {
17 printf("打印目录下的文件名\n");
18 }
19 else if(strcmp(argv[1],"-b")==0)
20 {
21 printf("打印目录下的文件的详细信息\n");
22 }
23 else if(strcmp(argv[1],"-c")==0)
24 {
25 printf("打印目录下文件的隐藏信息\n");
26 }
27 else
28 {
29 printf("待未开发\\n");
30 }
31
32 }
使用 make ,./mytest 执行可执行程序
[yzq@VM-8-8-centos my]$ ./mytest
usage:./mytest-[a|b|c]
[yzq@VM-8-8-centos my]$ ./mytest -a
打印目录下的文件名
[yzq@VM-8-8-centos my]$ ./mytest -b
打印目录下的文件的详细信息
[yzq@VM-8-8-centos my]$ ./mytest -c
打印目录下文件的隐藏信息
[yzq@VM-8-8-centos my]$ ./mytest -d
待未开发
相当于使用ls 、ls -l 、ls -la 指令,选项以字符串形式以命令行参数传递给了程序,程序内部对选项做判断,就可使同样的ls ,携带不同的选项,就可表现不同的现象
权限代表能不能的问题,优先级代表已经能,谁先谁后的问题
比如 权限:若你考完试,你能够自己去老师教室翻阅自己的卷子么,当然不能,没有权限
优先级:若你在食堂排队,你可以打饭,但是有先后顺序
ps -l 查看当前系统的进程优先级
[yzq@VM-8-8-centos my]$ ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 R 1002 3722 17835 0 80 0 - 38324 - pts/0 00:00:00 ps
0 S 1002 17835 17834 0 80 0 - 29280 do_wai pts/0 00:00:00 bash
PRI代表当前进程的优先级
NI代表当前进程优先级的修正数据
UID代表当前用户的身份标识
PRI数字值越小,优先级越高
PRI(new)=PRI(old)+NI(nice)
一般调整的是nice值,nice值取值范围是[-20-19]
调度器的作用是一碗水端平,让每一个进程有享有资源,所以不支持将一个进程的PRI调整过小,从而导致优先级过高
在test.c中修改为以下内容
#include<stdio.h>
2 #include<unistd.h>
3 int main()
4 {
5 while(1)
6 {
7 printf(".");
8 fflush(stdout);//刷新缓冲区
9 sleep(1);
10 }
11 return 0;
12 }
使用./mytest运行程序,并复制SSH渠道 创建终端2
在保证终端1mytest运行的情况下,在终端2中使用 ps -la ,找到mytest进程
[yzq@VM-8-8-centos my]$ ps -la
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 1002 8561 17835 0 80 0 - 1054 hrtime pts/0 00:00:00 mytest
0 R 1002 9135 23362 0 80 0 - 38332 - pts/1 00:00:00 ps
再次在终端2中使用 top 指令,输入 r(renice),出现如下数据
PID to renice [default pid = 7429]
在上一步输入的 ps -la指令中查询mytest的PID

使用q退出
再次输入 ps -la指令
[yzq@VM-8-8-centos my]$ ps -la
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 1002 8561 17835 0 90 10 - 1054 hrtime pts/0 00:00:00 mytest
0 R 1002 12141 23362 0 80 0 - 38332 - pts/1 00:00:00 ps
发现刚刚修改nice值为10 ,PID值变为90

我想用ruby编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',
我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是
我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
两者都可以defsetup(options={})options.reverse_merge:size=>25,:velocity=>10end和defsetup(options={}){:size=>25,:velocity=>10}.merge(options)end在方法的参数中分配默认值。问题是:哪个更好?您更愿意使用哪一个?在性能、代码可读性或其他方面有什么不同吗?编辑:我无意中添加了bang(!)...并不是要询问nobang方法与bang方法之间的区别 最佳答案 我倾向于使用reverse_merge方法:option