-1

質問は本当にばかげているかもしれませんが、私は今朝からこのコードに取り組んでおり、今ではばかげたことでさえ難しいです:\

このコードを取得し、8 つのプロセスを作成して呼び出し、それらを実行します。次に、この 8 つのプロセスに関する情報を出力する必要がある別のスレッドがあります。(コードは以下です)。

import MSCHAPV2
import threading
import binascii
import multiprocessing

class CrackerThread(multiprocessing.Process):

    password_header = "s."
    current_pin = ""
    username = ""
    server_challenge = ""
    peer_challenge = ""
    nt_response = ""
    starting_pin = 0
    limit = 0
    testing_pin = 0
    event = None

    def __init__(self, username, server_challenge, peer_challenge, nt_response, starting_pin, limit, event):
        #threading.Thread.__init__(self)
        super(CrackerThread, self).__init__()
        self.username = username
        self.server_challenge = server_challenge
        self.peer_challenge = peer_challenge
        self.nt_response = nt_response
        self.starting_pin = starting_pin
        self.limit = limit
        self.event = event
        self.testing_pin = starting_pin        
        #self.setDaemon(True)

    def run(self):        
        mschap = MSCHAPV2.MSCHAPV2()
        pin_range = self.starting_pin+self.limit
        while self.testing_pin <= pin_range and not self.event.isSet():
            self.current_pin = "%s%08d" % (self.password_header, self.testing_pin)                      
            if(mschap.CheckPassword(self.server_challenge, self.peer_challenge, self.username, self.current_pin.encode("utf-16-le"), self.nt_response)):
                self.event.set()
                print "Found valid password!"
                print "user     =", self.username
                print "password =", self.current_pin                
            self.testing_pin+=1            
        print "Thread for range (%d, %d) ended with no success." % (self.starting_pin, pin_range)

    def getCurrentPin(self):        
        return self.testing_pin

def printCrackingState(threads):
    info_string = '''
    ++++++++++++++++++++++++++++++++++
    + Starting password = s.%08d +
    +--------------------------------+    
    + Current pin       = s.%08d +
    ++++++++++++++++++++++++++++++++++
    + Missing pins      =   %08d +
    ++++++++++++++++++++++++++++++++++
                  '''

    while 1:        
        for t in threads:            
            printed_string = info_string % (t.starting_pin, t.getCurrentPin(), t.getMissingPinsCount())
            sys.stdout.write(printed_string)
        sys.stdout.write("--------------------------------------------------------------------")
        time.sleep(30)

printCrackingState私の「メイン」のこれらの行によって呼び出されます:

infoThread = threading.Thread(target = utils.printCrackingState, args=([processes]))  
#infoThread = cursesTest.CursesPrinter(threads, processes, event)    
infoThread.setDaemon(True)
infoThread.start() 

問題は、なぜ同じ値t.starting_pinを出力するのかということです。メソッドで設定された値を返し、インクリメントしていることを認識していないようですt.getCurrentPin()!t.getCurrentPin()__init__()

提案?

4

1 に答える 1

2

ここでの問題は、あるプロセスで変数を更新し、別のプロセスで読み取ろうとしているということです。そんなことはできません。マルチスレッド化とは対照的に、マルチプロセッシングの要点は、変数がデフォルトで共有されないことです。

ドキュメント、特にExchangeing objects between processesSharing state between processesを読むと、これに関するさまざまな方法が説明されます。しかし、実際には2つあります。親プロセスが子プロセスに現在の状態を要求できるようにするために何らかのチャネル/APIが必要か、データを保存するために何らかの共有メモリが必要です。そして、ロックが必要になる場合がありますチャネル/共有メモリのいずれかを保護します。

ここでは共有メモリが「明白な」答えのように思えるかもしれませんが、次の時間を計ることができます。

val = 0
for i in range(10000):
    val += 1

val = Value('i', 0)
lock = Lock()
for i in range(10000):
    with lock:
        val.value += 1

CPython ではおそらく機能しますが、コードがスレッドでも正しくないことに注意してください。同期を行わない場合、順序は保証されません。あるスレッドで値を書き込み、それを別のスレッドで「後で」読み取る場合でも、古い値を読み取ることができます。後どれくらい?スレッド 0 がコア 0 で実行され、スレッド 1 がコア 1 で実行され、両方のキャッシュに変数があり、誰も CPU にキャッシュをフラッシュするように指示しない場合、スレッド 1 は古い値を永久に読み取り続けます。実際には、CPython の Global Interpreter Lock は最終的にすべてを暗黙的に同期し (つまり、無限ではなくミリ秒について話している)、すべての変数には、たとえばレジスタなどに最適化されるのではなく、明示的なメモリ位置があるため、通常は逃げることができます。保護されていないレースを書くことで。

于 2013-03-29T18:22:32.717 に答える