博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
setsid的作用
阅读量:4167 次
发布时间:2019-05-26

本文共 3784 字,大约阅读时间需要 12 分钟。

百度了一圈setsid的作用,基本都是一个抄袭一个,真的是太桑心,引用百度百科原话:

当进程是会话的领头进程时setsid()调用失败并返回(-1)。

setsid()调用成功后,返回新的会话的ID,调用setsid函数的进程成为新的会话的领头进程,并与其父进程的会话组和进程组脱离。
由于会话对控制终端的独占性,进程同时与控制终端脱离。

这段解释比较费解,用代码说明:

[cpp] 
 
  1. #include <sys/file.h>  
  2. #include <stdio.h>  
  3. #include <unistd.h>  
  4. #include <stdlib.h>  
  5. #include <sys/file.h>  
  6.                                           
  7. int main (int argc, char ** argv)  
  8. {  
  9.      if ( fork() > 0 ) {  
  10.           printf ( "parent begin\n" ) ;  
  11.           sleep(10);  
  12.             
  13.         printf ( "parent exit\n" ) ;  
  14.         exit ( 0 ) ;  
  15.      }  
  16.        
  17.      printf ( "child begin\n" ) ;  
  18.      sleep(100);  
  19.        
  20.      printf ( "child exit\n" ) ;  
  21.      return 0 ;  
  22. }  


上面这段代码,运行时父进程等待10s,子进程等待100s

应用启动:

打开另外一个终端窗口,查看进程存在,testSetSid同在一个进程组:

关闭运行testSetSid的终端运行窗口,再查看进程,进程组退出,父子进程都已不在:

说明:父子进程都受终端影响,终端退出,父子进程也会退出

如果我们在子进程开始时调用setsid():

[cpp] 
 
  1. #include <sys/file.h>  
  2. #include <stdio.h>  
  3. #include <unistd.h>  
  4. #include <stdlib.h>  
  5. #include <sys/file.h>  
  6.                                           
  7. int main (int argc, char ** argv)  
  8. {  
  9.      if ( fork() > 0 ) {  
  10.           printf ( "parent begin\n" ) ;  
  11.           sleep(10);  
  12.             
  13.         printf ( "parent exit\n" ) ;  
  14.         exit ( 0 ) ;  
  15.      }  
  16.        
  17.      <span style="color:#ff0000;">setsid();</span>  
  18.      printf ( "child begin\n" ) ;  
  19.      sleep(100);  
  20.        
  21.      printf ( "child exit\n" ) ;  
  22.      return 0 ;  
  23. }  


重新启动应用:

查看进程,testSetSid分为两个进程组:

关闭运行testSetSid的终端窗口,查看进程,父进程退出,子进程继续存在:

说明:setsid后子进程不受终端影响,终端退出,不影响子进程

程序中umask(0)什么意思?

linux中的 umask 函数主要用于:在创建新文件或目录时 屏蔽掉新文件或目录不应有的访问允许权限。文件的访问允许权限共有9种,分别是:r w x r w x r w x(它们分别代表:用户读 用户写 用户执行 组读 组写 组执行 其它读 其它写 其它执行)。 其实这个函数的作用,就是设置允许当前进程创建文件或者目录最大可操作的权限,比如这里设置为0,它的意思就是0取反再创建文件时权限相与,也就是:(~0) & mode 等于八进制的值0777 & mode了,这样就是给后面的代码调用函数mkdir给出最大的权限,避免了创建目录或文件的权限不确定性。
open("/dev/null",o_rdwr)作用  open("/dev/null",..) 很多程序在一开始的时候要做这样的处理 /*  * make sure we have stdin/stdout/stderr reserved */ while((t = open("/dev/null",O_RDWR)) < 3 && T >= 0) if(t >= 3) close(t) 写入/dev/null的东西会被系统丢掉 就像注释写的那样,对stdin/stdout/stderr进行保护 代码中利用while先把文件描述符0,1,2分配出去,以后再分配 的时候就不会将stdin/stdout/stderr打开,以达到保护目的。 linux下的stdin,stdout,stderr详解   
stdout, stdin, stderr的中文名字分别是标准输出,标准输入和标准错误。
 
在Linux下,当一个用户进程被创建的时候,系统会自动为该进程创建三个数据
流,也就是题目中所提到的这三个。那么什么是数据流呢(stream)?我们知道,一个程序要运行,需要有输入、输出,如果出错,还要能表现出自身的错误。这是就要从某个地方读入数据、将数据输出到某个地方,这就够成了数据流。
 
因此,一个进程初期所拥有的这么三个数据流,就分别是标准输出、标准输入和标准错误,分别用stdout, stdin, stderr来表示。对于这三个数据流来说,默认是表现在用户终端上的,比如我们在c中使用fprintf:
fprintf(stdout,"hello world!\n");
 
屏幕上将打印出"hello world!"来,同样,我们使用:
上面的代码会接收用户输入在终端里的字符,并存在ptr中。
fread(ptr,1,10,stdin);
 
那么标准输入输出和错误是不是只能反应在终端里呢?答案是不是的!我们可以
将标准输入和输出重定位到文件中:
例如,我们使用ls命令,会把当前目录下的文件名输出到终端上:
$ls
gcc  gcc.sh gmp-5.0.1 gmp-5.0.1.tar.bz2
linux-loongson-community-2.6.35-rc1 longene-0.3.0-linux-2.6.34
mpfr-3.0.0 mpfr-3.0.0.tar.gz oprofile-0.9.6
我们可以使用“ > ”符号,将ls的标准输出重定向到文件中:
$ls  >  lsout 将标准输出重定向为文件lsout
$more  lsout 显示lsout文件里的内容
gcc  gcc.sh gmp-5.0.1 gmp-5.0.1.tar.bz2
linux-loongson-community-2.6.35-rc1 longene-0.3.0-linux-2.6.34
mpfr-3.0.0 mpfr-3.0.0.tar.gz oprofile-0.9.6
同样,我们也可以使用“ < ”符号将标准输入重定向到文件中,以sort为例,以下示例使用 sort命令对由键盘键入的文本进行排序。键入ctrl-D 结束标准输入。终端屏幕显示的标准输出如下:
$sort
muffy
happy
bumpy
CTRL-D //结束标准输入。
 
bumpy
happy
muffy //结束标准输出。
 
使用" < "重定向后为:
$ more socks 显示 socks的内容。
polka dot
argyle
plaid 
 
$ sort < socks 将输入重定向为从 socks输入,并将内容排序。
argyle
plaid
polka dot
好,基本知识讲完了,我们知道,标准输出和标准错误默认都是将信息输出到终端上,那么他们有什么区别呢?让我们来看个题目:
 
问题:下面程序的输出是什么?(intell笔试2011)
Int  main(){
fprintf(stdout,"Hello ");
fprintf(stderr,"World!");
return0;
}
解答:这段代码的输出是什么呢?你可以快速的将代码敲入你电脑上(当然,拷贝更快),然后发现输出是
World! Hello
这是为什么呢?在默认情况下,stdout是行缓冲的,他的输出会放在一个buffer里面,只有到换行的时候,才会输出到屏幕。而stderr是无缓冲的,会直接输出,举例来说就是printf(stdout, "xxxx") 和 printf(stdout, "xxxx\n"),前者会憋住,直到遇到新行才会一起输出。而printf(stderr, "xxxxx"),不管有么有\n,都输出。

你可能感兴趣的文章
1136 . 欧拉函数
查看>>
面试题:强制类型转换
查看>>
Decorator模式
查看>>
Template模式
查看>>
Observer模式
查看>>
高性能服务器设计
查看>>
图文介绍openLDAP在windows上的安装配置
查看>>
Pentaho BI开源报表系统
查看>>
Pentaho 开发: 在eclipse中构建Pentaho BI Server工程
查看>>
android中SharedPreferences的简单例子
查看>>
android中使用TextView来显示某个网址的内容,使用<ScrollView>来生成下拉列表框
查看>>
andorid里关于wifi的分析
查看>>
Spring MVC和Struts2的比较
查看>>
Hibernate和IBatis对比
查看>>
Spring MVC 教程,快速入门,深入分析
查看>>
Android 的source (需安装 git repo)
查看>>
LOCAL_PRELINK_MODULE和prelink-linux-arm.map
查看>>
Ubuntu Navicat for MySQL安装以及破解方案
查看>>
java多线程中的join方法详解
查看>>
idea添加gradle模块报错The project is already registered
查看>>