管道之popen,pclose函式
方法6的popen,pclose函式:
#include <stdio.h>
FILE *popen(const char *cmdstring, const char *type);
int pclose(FILE *fp);
返回值:cmdstring(shell)的終止狀態,若出錯則返回-1
popen函式:
pipe---->fork---->exec :建立一個管道,呼叫fork產生一個子程序,關閉管道的不使用端,執行一個shell以執行命令.
執行fp = popen(cmdstring, “r”)函式的結果
type為’r’連線到cmdstring
的標準輸出; 此時fp相當於管道的fd[0], stdout相當於管道的fd[1].返回一個指向fd[1] 端的FILE檔案指標,然後從fd讀取該資料
type為’w’連線到cmdstring的標準輸入,此時fp相當於管道的fd[1], stdin相當於管道的fd[0].
返回fp, 往fp寫,也就寫到了子程序的fd[0],把寫入的資料(命令)給/bin/sh 執行.
pclose 函式: 關閉標準i/o流,然後等待命令終止。
用popen向分頁程式傳送檔案:
#include "apue.h"
#include <sys/wait.h>
#define
intmain(int argc, char *argv[])
{
char line[MAXLINE];
FILE *fpin, *fpout;
if(argc != 2) err_quit("usage: a.out <pathname>");
if((fpin = fopen(argv[1], "r")) == NULL)err_sys("can't open %s", argv[1]);
if((fpout =
popen(PAGER, "w")
/* copy argv[1] to pager */
while(fgets(line, MAXLINE, fpin) != NULL)
{
if(fputs(line, fpout) == EOF) err_sys("fputs error to pipe");
}
if(ferror(fpin))err_sys("fgets error");
if(pclose(fpout) == -1)err_sys("pclose error");
exit(0);
}
執行:
popen,pclose函式的實現:
1. #include <errno.h>
1. #include <fcntl.h>
2. #include <stdio.h>
3. #include <unistd.h>
4. static pid_t *childpid =NULL;
5. static int maxfd;
6.
7. FILE *popen(const char *cmdstring,const char *type)
8. {
9. int i;
10. int pfd[2];
11. pid_t pid;
12. FILE *fp;
13.
14. /* only allow "r"or"w"*/
15. if((type[0]!='r'&& type[0]!='w')|| type[1]!= 0)
16. {
17. errno = EINVAL;/* required by POSIX */
18. return(NULL);
19. }
20.
21. if(childpid ==NULL)/* first time through */
22. {/* allocate zeroed out arrayfor child pids */
23. maxfd =open_max();//返回最大檔案描述符個數,其裡面實現用sysconf(_SC_OPEN_MAX)
24. if((childpid = calloc(maxfd, sizeof(pid_t)))==NULL)
25. return(NULL);
26. }
27.
28. if(pipe(pfd)< 0) return(NULL);/* errno set by pipe()*/
29. if (pfd[0] >= maxfd || pfd[1] >= maxfd )
30. { //maxfd < 管道檔案描述符,則認為很多檔案描述符是開啟的.
31. close(pfd[0]); close(pfd[1]); errnp = EMFILE; return (NULL);
32. }
33. if((pid = fork())< 0)
34. {
35. return(NULL);/* errno set by fork()*/
36. }
37. elseif(pid == 0)/* child */
38. {
39. if(*type =='r')
40. {
41. close(pfd[0]);
42. if(pfd[1]!= STDOUT_FILENO)
43. {
44. dup2(pfd[1], STDOUT_FILENO);
45. close(pfd[1]);
46. }
47. }
48. else
49. {
50. close(pfd[1]);
51. if(pfd[0]!= STDIN_FILENO)
52. {
53. dup2(pfd[0], STDIN_FILENO);
54. close(pfd[0]);
55. }
56. }
57.
58. for(i = 0; i < maxfd; i++)/* close all descriptors in childpid[]*/
59. if(childpid[i]> 0) close(i); //關閉呼叫open依舊開啟著的的檔案描述符.
60.
61. execl("/bin/sh","sh","-c", cmdstring,(char *)0);
62. _exit(127);
63. }
64.
65. if(*type =='r')/* parent continues...*/
66. {
67. close(pfd[1]);
if((fp =fdopen(pfd[0], type))==NULL) return(NULL);//將檔案描述符轉化為FILE* 指標.
68. }
69. else
70. {
71. close(pfd[0]);
72. if((fp =fdopen(pfd[1], type))==NULL)return(NULL);
73. }
74.
75. childpid[fileno(fp)]= pid;/* remember child pid for this fd */
76. return(fp);
77. }
78.
79. intpclose(FILE *fp)
80. {
81. int fd, stat;
82. pid_t pid;
83.
84. if(childpid ==NULL)
85. {
86. errno = EINVAL;
87. return(-1);/* popen() has never been called */
88. }
89.
90. fd = fileno(fp);
91. if((pid = childpid[fd])== 0)//通過檔案描述符得到程序id.
92. {
93. errno = EINVAL;
94. return(-1);/* fp wasn't opened by popen()*/
95. }
96.
97. childpid[fd]= 0;
98. if(fclose(fp)== EOF) return(-1);
99.
100. while(waitpid(pid,&stat, 0)< 0)
101. if(errno != EINTR) return(-1);/*error other than EINTR from waitpid()*/
102. /*核心不對SIGCHLD資訊排隊,如果有b個子程序同時結束,父程序會收到1個訊號,訊號處理函式中while就會迴圈n次,
103. 把所有結束的子程序處理掉,直到沒有已經結束的程序。*/
104. return(stat);/* return child's termination status */
105. }
Waitpid 和SIGCHLD訊號:
說明參考:
返回EINTR:
1、pclose的呼叫者已近註冊SIGCHLD訊號處理函式,呼叫pclose時,其內部的waitpid返回EINTR.
返回ECHILD:
1、popen的呼叫程序呼叫watpid獲取到popen子程序的退出狀態, 呼叫pclose時,其內部的waitpid返回ECHILD.
2、signal設定了忽略SIGCHLD訊號的情況下,核心會處理子程序的退出狀態並釋放子程序資源將,等父程序呼叫waitpid時,發現對應的pid進
程已不存在,因而返回-1錯誤,errno為10(No child processes).
Popen實現的過濾器:
注意,popen絕不應由設定使用者ID或設定使用者組ID程式呼叫。當它執行命令時,popen等同於:
execl("/bin/sh", "sh", "-c", command, NULL);
它在從呼叫者繼承的環境中執行shell,並由shell解釋執行command。一個心懷不軌的使用者可以操縱這種環境,使得shell能以設定ID檔案模式所授予的提升了的許可權以及非預期的方式執行命令。
popen特別適用於構造簡單的過濾器程式,它變換執行命令的輸入或輸出。當命令希望構造它自己的管道線時,就是這種情形。
例項
考慮一個應用程式,它向標準輸出寫一個提示,然後從標準輸入讀1行。使用popen,可以在應用程式和輸入之間插入一個程式以便對輸入進行變換處理。圖15-7顯示了為此做的程序安排。
圖15-7 用popen對輸入進行變換處理
對輸入進行的變化可能是路徑名擴充,或者是提供一種歷史機制(記住以前輸入的命令)。
程式清單15-6是一個簡單的過濾程式,它只是將標準輸入複製到標準輸出,在複製時,將所有大寫字元變換為小寫字元。在寫了一行以後,對標準輸出進行了沖洗(用fflush),其理由可參考程序間通訊之協同程序。
程式清單15-6 將大寫字元轉換成小寫字元的過濾程式
#include "apue.h"
#include <ctype.h>
intmain(void)
{
int c;
while((c = getchar()) != EOF)
{
if(isupper(c)) c = tolower(c);
if(putchar(c) == EOF) err_sys("output error");
if(c == '\n')fflush(stdout);
}
exit(0);
}
編譯該過濾程式,也就是編譯後的可執行檔名為myuclc,然後在程式清單15-7中用popen呼叫它們。
程式清單15-7 呼叫大寫/小寫過濾程式以讀取命令
#include "apue.h"
#include <sys/wait.h>
intmain(void)
{
char line[MAXLINE];
FILE *fpin;
if((fpin = popen("/home/zhu/apue/myuclc", "r")) == NULL)err_sys("popen error");
for(;;)
{
fputs("prompt> ", stdout);
fflush(stdout);
if(fgets(line, MAXLINE, fpin) == NULL) /*
read from pipe */
方法6的popen,pclose函式:
#include <stdio.h>
FILE *popen(const char *cmdstring,
const char *type
1、函式介紹
popen 和 pclose 函式
操作是建立一個管道連結到另一個程序,然後讀其輸出或向其輸入端傳送資料。標準 I/O 庫提供了兩個函式 popen 和 pclose 函式,這兩個函式實現的操作是:建立一個管道,呼叫 fork 建立一個子程序
基於管道的popen和pclose函式
https://my.oschina.net/renhc/blog/35116
標準I/O函式庫提供了popen函式,它啟動另外一個程序去執行一個shell命令列。
這裡我們稱呼叫popen的程序為父程序,由popen啟動的程序稱
就像百度百科中所說popen()函式通過建立一個管道,呼叫fork()產生一個子程序,執行一個shell以執行命令來開啟一個程序。這個管道必須由pclose()函式關閉。
其中”必須由pclose()函式關閉“是一個容易被忽視的點,這不光光浪費資源的問題,更涉及到子程序的週
因為一個普遍的操作是為另一個程序建立一個管道,或者讀它的輸出或向它傳送輸入,所以標準I/O庫歷史上提供了popen和pclose函式。這兩 個函式處理我們自己一直在做的髒活:建立一個管道、fork一個子程序、關閉管道無用的端,執行一個外殼來執行這個命令,等待命令終止。
#include <st
popen和pclose
標頭檔案
#include <stdio.h>
函式原型
FILE *popen(const char *command, const char *type)
本文針對專案中用到的幾個函式進行詳細分析,並儘可能的新增示例進行驗證學習。比如fcntl/ioctl函式、system/exec函式、popen/pclose函式、mmap函式等。 重點參考了《UNP》和《Linux程式設計》第四版。
一、概念
什麼是自執行函式?
顧名思義.就是不用呼叫,自己自動就會執行的函式;
為什麼要用自執行函式?
自執行函式內部是一個獨立的作用域,這樣就保持了一個相對獨立的名稱空間,避免汙染全域性作用域
怎麼建立自執行函式?
寫法一:(function(param){…})(re—param)
views檢視函式屬於MTV中邏輯處理的部分檢視函式包含著兩個物件,HttpRequest物件和HttpResponse物件
一.HttpRequest物件
HttpRequest物件在Django中會預設傳到views函式中作為第一個引數
HttpRequest的屬性:
檔案補充
操作檔案 讀寫 內部連結
read 一次讀取
readline 一行一行度 不知道在哪結束
readlines 一次讀取 修改檔案的原理 (檔案是不能修改的,實在一個檔案修改完成後刪除 原始檔 並改名)
with open('1.txt',
一、簡單的靜態庫書寫編譯和測試
檔案目錄如下所示:
.
├── Makefile
├── MakefileTest
├── include.c
├── include.h
└── main.c
0 directories, 5 files
其中main.c函式裡面會呼叫includ
P## 函式的定義 程式設計裡面的函式定義是:def作為關鍵字
def test(x) :
"The function definitions"
x+=1
return x
def:定義函式的關金子
test:函式名
():內可定義的形參
"文件描述(非
函式引數-動態引數
之前我們說過傳參,如果我們在傳引數的時候不很清楚有哪些的時候,或者說給一個函式傳了很多引數,我們就要寫很多,很麻煩怎麼辦呢,我們可以考慮使用動態引數
形參的第三種:動態引數
動態引數分為兩種:
1.動態接受位置引數
首先我們來回顧下位置引數
遞迴函式
遞迴函式一直都是我們所覺得難理解的以一種方式,但其實,也很好理解的,遞迴函式就是自己呼叫自己。就是在重複的做同一件事情。只是有的時候,也最好不要使用遞迴函式,因為你的函式一旦呼叫,就要開闢新的記憶體空間。不利於程式的執行。python對你記憶體一個保護機制,預設只能遞迴到998
一、函式的作用域:表示函式執行時的範圍 注意:返回函式名稱,即返回一個地址;簡單說就是:函式名稱即指代該函式地址,在呼叫函式時,需在函式名稱後面加括號:函式名稱()
如上面圖片中那樣的情況,再最後加兩行程式碼: dz3=dz2() #---接收foo2()函式執行的返回
SparkSQL中有兩種自定函式,在我們使用自帶的函式時無法滿足自己的需求時,可以使用自定義函式,SparkSQL中有兩種自定義函式,一種是UDF,另一種是UDAF,和Hive 很類似,但是hive中還有UDTF,一進多出,但是sparkSQL中沒有,這是因為spark中用 flatMap這
1.昨天函式的引數內容的補充
命名關鍵字引數: 在定義函式時,*與**之間引數稱之為命名關鍵字引數特點: 在呼叫函式時,命名關鍵字引數必須按照key=value的形式傳值
def func(x,*,y=1,z): 在這裡*後邊的y和z都是命名關鍵字引數,y像預設引數一樣被事先
一、函式的使用原則
函式的使用應該分為兩個明確的階段1. 定義階段:只檢測語法,不執行函式體程式碼 def func(): print('from func')2. 呼叫階段:會觸發函式體程式碼的執行 func()
函式使用的原則: 先定義後呼叫
什麼是函式(必會): 完成特定功能的程式碼塊 看一個示例:
//定義了一個函式p1,列印金字塔 public static void p1(){ System.out.println(" *"); System.out.println(" ***"); System.out.printl
import numpy as np
import pandas as pd
s1 = pd.Series(np.random.randint(-5,10,10))
s2 = pd.DataFrame(np.random.uniform(-5,10,(3,4)),index=list(' 相關推薦
管道之popen,pclose函式
linux c之通過popen和pclose函式建立管道執行shell 執行命令使用總結
基於管道的popen和pclose函式
popen()函式執行指令碼,要用pclose()函式關閉
程序間通訊--popen函式和pclose函式blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=25940216&id=3206312
Linux popen和pclose函式
Linux函式popen/pclose學習
javascript高階程式設計之--自執行函式
Django之views檢視函式
邁向大神之路 day8 函式(一)……
make之makefile 十 函式庫檔案
Python之路-Day06函式
萬惡之源 - Python函式進階
python之遞迴函式,二分查詢
python之自定義函式、傳參、作用域
SparkSQL之自定義函式UDF和UDAF
我的Python成長之路---Day11-函式的使用及名稱空間和作用域
我的Python成長之路---Day10-函式的基本使用
JavaSE之路10--函式
python之pandas的函式排序